changeset 54084:84f10bbf993f

8218074: Update Graal Reviewed-by: kvn
author jwilhelm
date Tue, 12 Mar 2019 19:17:42 +0100
parents d9bcf74fc56a
children ab87b06dfdc0
files make/CompileJavaModules.gmk make/test/JtregGraalUnit.gmk src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Linker.java src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSearch.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64BaseAssembler.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCAssembler.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.test/src/org/graalvm/compiler/asm/test/AssemblerTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/BranchTargetOutOfBoundsException.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/HexCodeFileDisassemblerProvider.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64CbzTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64MembarOpTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64TestBitAndBranchTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRGenerator.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/SpeculativeExecutionAttacksMitigations.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractBlockBase.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/CFGVerifier.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/Loop.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/doc-files/MitigateSpeculativeExecutionAttacksHelp.txt src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/AbstractObjectStamp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/AbstractPointerStamp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IllegalStamp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ObjectStamp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/PrimitiveStamp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/Stamp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/StampPair.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/SymbolicJVMCIReference.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/VoidStamp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/UnsignedLong.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CountedLoopTest2.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DumpPathTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphEncoderTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardPrioritiesTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IntegerDivRemConstantTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryScheduleTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NestedLoopTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SwitchCanonicalizerTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyCallerSensitiveMethods.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyDebugUsage.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/BackendTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/RethrowDeoptMaterializeTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/LIRCompilerBackend.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/LIRGenerationProvider.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/HighTier.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/LowTier.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugOptions.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/IgvDumpChannel.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/PathUtilities.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/doc-files/PrintGraphHelp.txt src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/graphio/GraphOutputTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotJumpToExceptionHandlerInCallerOp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/BinaryMathStubTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/UnaryMathStubTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMaths.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64MathStub.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64X87MathIntrinsicNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64X87MathSnippets.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.jdk9.test/src/org/graalvm/compiler/hotspot/jdk9/test/StringUTF16ToBytesGetCharsTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.lir.test/src/org/graalvm/compiler/hotspot/lir/test/BenchmarkCounterOverflowTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackend.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotMove.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/EliminateRedundantInitializationPhaseTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/JVMCIInfopointErrorTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/OptionsInFileTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ReservedStackAccessTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierAdditionTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierVerificationTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotDataBuilder.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalJVMCIServiceLocator.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalOptionValues.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotTTYStreamProvider.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/gc/g1/G1ArrayRangePostWriteBarrier.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/gc/g1/G1ArrayRangePreWriteBarrier.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/gc/g1/G1BarrierSet.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/gc/g1/G1PostWriteBarrier.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/gc/g1/G1PreWriteBarrier.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/gc/g1/G1ReferentFieldReadBarrier.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/gc/shared/ArrayRangeWriteBarrier.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/gc/shared/BarrierSet.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/gc/shared/CardTableBarrierSet.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/gc/shared/ObjectWriteBarrier.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/gc/shared/SerialArrayRangeWriteBarrier.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/gc/shared/SerialWriteBarrier.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotClassInitializationPlugin.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraalConstantFieldProvider.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotNodePlugin.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotUnsafeSubstitutions.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotWordOperationPlugin.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/AllocaNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/ArrayRangeWriteBarrier.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DimensionsNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ArrayRangePostWriteBarrier.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ArrayRangePreWriteBarrier.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1PostWriteBarrier.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1PreWriteBarrier.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ReferentFieldReadBarrier.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/ObjectWriteBarrier.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SerialArrayRangeWriteBarrier.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SerialWriteBarrier.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/type/KlassPointerStamp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierAdditionPhase.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierVerificationPhase.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ArraysSupportSubstitutions.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CounterModeSubstitutions.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/DigestBaseSubstitutions.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotClassSubstitutions.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA2Substitutions.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA5Substitutions.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHASubstitutions.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/StringUTF16Substitutions.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/OutOfBoundsExceptionStub.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/IntegerExactOpSpeculation.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/IfNodeCanonicalizationsTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/SwitchHashTableTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Call.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ControlFlow.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayEqualsOp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ControlFlow.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64HotSpotHelper.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MathCosOp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MathExpOp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MathIntrinsicBinaryOp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MathIntrinsicUnaryOp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MathLog10Op.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MathLogOp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MathPowOp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MathSinOp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64MathTanOp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/SPARCBranchBailoutTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIR.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRValueUtil.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/StandardOp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/Variable.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/ssa/SSALinearScanLifetimeAnalysisPhase.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/DataBuilder.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/ArithmeticLIRGenerator.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerator.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGeneratorTool.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/hashing/HashFunction.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/hashing/Hasher.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ssa/SSAUtil.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/ConvertDeoptimizeToGuardPhase.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopTransformations.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/BasicInductionVariable.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/CountedLoopInfo.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/DefaultLoopPolicies.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/DerivedConvertedInductionVariable.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/DerivedOffsetInductionVariable.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/DerivedScaledInductionVariable.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/InductionVariable.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopEx.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragment.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentInside.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentWhole.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/MathUtil.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/org/graalvm/compiler/microbenchmarks/lir/GraalCompilerState.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/IfNodeCanonicalizationTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/AbstractFixedGuardNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ComputeObjectAddressNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ConstantNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/EncodedGraph.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FrameState.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphEncoder.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/LogicNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/LoopBeginNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/LoopExitNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PiNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/BinaryArithmeticNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerDivRemNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerEqualsNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLessThanNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerMulHighNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IsNullNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/RightShiftNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedDivNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedRemNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnsignedRightShiftNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/Block.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/JavaReadNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GeneratedInvocationPlugin.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderConfiguration.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderContext.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/MethodSubstitutionPlugin.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/NodePlugin.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/NewArrayNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/address/IndexAddressNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/NodeLIRBuilderTool.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/Replacements.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/type/NarrowOopStamp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options.processor/src/org/graalvm/compiler/options/processor/OptionProcessor.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionDescriptor.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionKey.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionValues.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionsParser.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConvertDeoptimizeToGuardPhase.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FixReadsPhase.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/OptimizeDivPhase.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/RemoveValueProxyPhase.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ReentrantBlockIterator.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/GraphOrder.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinterDumpHandler.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64MathSubstitutions.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringLatin1Substitutions.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringSubstitutions.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringUTF16Substitutions.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedPlugin.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/DeoptimizeOnIntegerExactTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/IntegerExactFoldTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ReplacementsParseTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringCompareToTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringIndexOfTestBase.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/classfile/ClassfileBytecodeProviderTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/GraphKit.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/IntrinsicGraphBuilder.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetCounter.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetIntegerHistogram.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StringUTF16Substitutions.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyCallNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopySnippets.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ArrayCompareToNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ArrayRegionEqualsNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicObjectCloneNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BinaryMathIntrinsicNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/UnaryMathIntrinsicNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerAddExactNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerAddExactOverflowNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerExactArithmeticNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerExactArithmeticSplitNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerExactOverflowNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerMulExactNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerMulExactOverflowNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerMulHighNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerSubExactNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/arithmetic/IntegerSubExactOverflowNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/GraalServices.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/JavaVersionUtil.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/SpeculationReasonGroup.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/GraalTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/SubprocessUtil.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsClosure.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphOutput.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphProtocol.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/ProtocolImpl.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/DirectAnnotationAccess.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/GuardedAnnotationAccess.java test/hotspot/jtreg/ProblemList-graal.txt test/hotspot/jtreg/compiler/graalunit/EA9Test.java test/hotspot/jtreg/compiler/graalunit/HotspotJdk9Test.java test/hotspot/jtreg/compiler/graalunit/TestPackages.txt
diffstat 316 files changed, 18112 insertions(+), 9427 deletions(-) [+]
line wrap: on
line diff
--- a/make/CompileJavaModules.gmk	Tue Mar 12 12:12:01 2019 -0700
+++ b/make/CompileJavaModules.gmk	Tue Mar 12 19:17:42 2019 +0100
@@ -461,6 +461,7 @@
     org.graalvm.compiler.debug.test \
     org.graalvm.compiler.graph.test \
     org.graalvm.compiler.hotspot.amd64.test \
+    org.graalvm.compiler.hotspot.jdk9.test \
     org.graalvm.compiler.hotspot.lir.test \
     org.graalvm.compiler.hotspot.sparc.test \
     org.graalvm.compiler.hotspot.test \
--- a/make/test/JtregGraalUnit.gmk	Tue Mar 12 12:12:01 2019 -0700
+++ b/make/test/JtregGraalUnit.gmk	Tue Mar 12 19:17:42 2019 +0100
@@ -92,6 +92,7 @@
               $(SRC_DIR)/org.graalvm.compiler.debug.test/src \
               $(SRC_DIR)/org.graalvm.compiler.graph.test/src \
               $(SRC_DIR)/org.graalvm.compiler.hotspot.amd64.test/src \
+              $(SRC_DIR)/org.graalvm.compiler.hotspot.jdk9.test/src \
               $(SRC_DIR)/org.graalvm.compiler.hotspot.lir.test/src \
               $(SRC_DIR)/org.graalvm.compiler.hotspot.sparc.test/src \
               $(SRC_DIR)/org.graalvm.compiler.hotspot.test/src \
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Linker.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Linker.java	Tue Mar 12 19:17:42 2019 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,10 @@
 import java.io.File;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
 import java.util.stream.Stream;
 
 final class Linker {
@@ -46,9 +50,12 @@
         return libraryFileName;
     }
 
+    private static Stream<String> getLines(InputStream stream) {
+        return new BufferedReader(new InputStreamReader(stream)).lines();
+    }
+
     private static String getString(InputStream stream) {
-        BufferedReader br = new BufferedReader(new InputStreamReader(stream));
-        Stream<String> lines = br.lines();
+        Stream<String> lines = getLines(stream);
         StringBuilder sb = new StringBuilder();
         lines.iterator().forEachRemaining(e -> sb.append(e));
         return sb.toString();
@@ -150,9 +157,18 @@
     }
 
     /**
-     * Search for Visual Studio link.exe Search Order is: VS2013, VS2015, VS2012.
+     * Search for Visual Studio link.exe Search Order is: VS2017+, VS2013, VS2015, VS2012.
      */
-    private static String getWindowsLinkPath() {
+    private static String getWindowsLinkPath() throws Exception {
+        try {
+            Path vc141NewerLinker = getVC141AndNewerLinker();
+            if (vc141NewerLinker != null) {
+                return vc141NewerLinker.toString();
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
         String link = "\\VC\\bin\\amd64\\link.exe";
 
         /**
@@ -183,10 +199,46 @@
         return null;
     }
 
+    private static Path getVC141AndNewerLinker() throws Exception {
+        String programFilesX86 = System.getenv("ProgramFiles(x86)");
+        if (programFilesX86 == null) {
+            throw new InternalError("Could not read the ProgramFiles(x86) environment variable");
+        }
+        Path vswhere = Paths.get(programFilesX86 + "\\Microsoft Visual Studio\\Installer\\vswhere.exe");
+        if (!Files.exists(vswhere)) {
+            return null;
+        }
+
+        ProcessBuilder processBuilder = new ProcessBuilder(vswhere.toString(), "-requires",
+                        "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", "-property", "installationPath", "-latest");
+        processBuilder.redirectOutput(ProcessBuilder.Redirect.PIPE);
+        processBuilder.redirectError(ProcessBuilder.Redirect.PIPE);
+        Process process = processBuilder.start();
+        final int exitCode = process.waitFor();
+        if (exitCode != 0) {
+            String errorMessage = getString(process.getErrorStream());
+            if (errorMessage.isEmpty()) {
+                errorMessage = getString(process.getInputStream());
+            }
+            throw new InternalError(errorMessage);
+        }
+
+        String installationPath = getLines(process.getInputStream()).findFirst().orElseThrow(() -> new InternalError("Unexpected empty output from vswhere"));
+        Path vcToolsVersionFilePath = Paths.get(installationPath, "VC\\Auxiliary\\Build\\Microsoft.VCToolsVersion.default.txt");
+        List<String> vcToolsVersionFileLines = Files.readAllLines(vcToolsVersionFilePath);
+        if (vcToolsVersionFileLines.isEmpty()) {
+            throw new InternalError(vcToolsVersionFilePath.toString() + " is empty");
+        }
+        String vcToolsVersion = vcToolsVersionFileLines.get(0);
+        Path linkPath = Paths.get(installationPath, "VC\\Tools\\MSVC", vcToolsVersion, "bin\\Hostx64\\x64\\link.exe");
+        if (!Files.exists(linkPath)) {
+            throw new InternalError("Linker at path " + linkPath.toString() + " does not exist");
+        }
+
+        return linkPath;
+    }
+
     // @formatter:off (workaround for Eclipse formatting bug)
-    /**
-     * Visual Studio supported versions Search Order is: VS2013, VS2015, VS2012.
-     */
     enum VSVERSIONS {
         VS2013("VS120COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\bin\\amd64\\link.exe"),
         VS2015("VS140COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\bin\\amd64\\link.exe"),
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java	Tue Mar 12 19:17:42 2019 +0100
@@ -166,7 +166,7 @@
                 printer.printInfo(classesToCompile.size() + " classes found");
             }
 
-            OptionValues graalOptions = HotSpotGraalOptionValues.HOTSPOT_OPTIONS;
+            OptionValues graalOptions = HotSpotGraalOptionValues.defaultOptions();
             // Setting -Dgraal.TieredAOT overrides --compile-for-tiered
             if (!TieredAOT.hasBeenSet(graalOptions)) {
                 graalOptions = new OptionValues(graalOptions, TieredAOT, options.tiered);
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSearch.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSearch.java	Tue Mar 12 19:17:42 2019 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,6 +30,7 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.function.BiConsumer;
+import java.io.File;
 
 public final class ClassSearch {
     private final List<SourceProvider> providers = new ArrayList<>();
@@ -106,7 +107,7 @@
 
     public static List<SearchFor> makeList(String type, String argument) {
         List<SearchFor> list = new ArrayList<>();
-        String[] elements = argument.split(":");
+        String[] elements = argument.split(File.pathSeparator);
         for (String element : elements) {
             list.add(new SearchFor(element, type));
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java	Tue Mar 12 19:17:42 2019 +0100
@@ -880,15 +880,15 @@
     protected void tbnz(Register reg, int uimm6, int imm16, int pos) {
         assert reg.getRegisterCategory().equals(CPU);
         assert NumUtil.isUnsignedNbit(6, uimm6);
-        assert NumUtil.isSignedNbit(18, imm16);
-        assert (imm16 & 3) == 0;
+        assert NumUtil.isSignedNbit(16, imm16) : String.format("Offset value must fit in 16 bits signed: 0x%x", imm16);
+        assert (imm16 & 3) == 0 : String.format("Lower two bits must be zero: 0x%x", imm16 & 3);
         // size bit is overloaded as top bit of uimm6 bit index
         int size = (((uimm6 >> 5) & 1) == 0 ? 32 : 64);
         // remaining 5 bits are encoded lower down
-        int uimm5 = uimm6 >> 1;
-        int offset = (imm16 & NumUtil.getNbitNumberInt(16)) >> 2;
+        int uimm5 = uimm6 & 0x1F;
+        int imm14 = (imm16 & NumUtil.getNbitNumberInt(16)) >> 2;
         InstructionType type = generalFromSize(size);
-        int encoding = type.encoding | TBNZ.encoding | (uimm5 << 19) | (offset << 5) | rd(reg);
+        int encoding = type.encoding | TBNZ.encoding | (uimm5 << 19) | (imm14 << 5) | rd(reg);
         if (pos == -1) {
             emitInt(encoding);
         } else {
@@ -907,15 +907,15 @@
     protected void tbz(Register reg, int uimm6, int imm16, int pos) {
         assert reg.getRegisterCategory().equals(CPU);
         assert NumUtil.isUnsignedNbit(6, uimm6);
-        assert NumUtil.isSignedNbit(18, imm16);
-        assert (imm16 & 3) == 0;
+        assert NumUtil.isSignedNbit(16, imm16) : String.format("Offset value must fit in 16 bits signed: 0x%x", imm16);
+        assert (imm16 & 3) == 0 : String.format("Lower two bits must be zero: 0x%x", imm16 & 3);
         // size bit is overloaded as top bit of uimm6 bit index
         int size = (((uimm6 >> 5) & 1) == 0 ? 32 : 64);
         // remaining 5 bits are encoded lower down
-        int uimm5 = uimm6 >> 1;
-        int offset = (imm16 & NumUtil.getNbitNumberInt(16)) >> 2;
+        int uimm5 = uimm6 & 0x1F;
+        int imm14 = (imm16 & NumUtil.getNbitNumberInt(16)) >> 2;
         InstructionType type = generalFromSize(size);
-        int encoding = type.encoding | TBZ.encoding | (uimm5 << 19) | (offset << 5) | rd(reg);
+        int encoding = type.encoding | TBZ.encoding | (uimm5 << 19) | (imm14 << 5) | rd(reg);
         if (pos == -1) {
             emitInt(encoding);
         } else {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java	Tue Mar 12 19:17:42 2019 +0100
@@ -33,6 +33,9 @@
 import static org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.AddressGenerationPlan.WorkPlan.ADD_TO_BASE;
 import static org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.AddressGenerationPlan.WorkPlan.ADD_TO_INDEX;
 import static org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.AddressGenerationPlan.WorkPlan.NO_WORK;
+
+import org.graalvm.compiler.asm.BranchTargetOutOfBoundsException;
+
 import static jdk.vm.ci.aarch64.AArch64.CPU;
 import static jdk.vm.ci.aarch64.AArch64.r8;
 import static jdk.vm.ci.aarch64.AArch64.r9;
@@ -1452,7 +1455,7 @@
      *
      * @param cmp general purpose register. May not be null, zero-register or stackpointer.
      * @param uimm6 Unsigned 6-bit bit index.
-     * @param label Can only handle 21-bit word-aligned offsets for now. May be unbound. Non null.
+     * @param label Can only handle 16-bit word-aligned offsets for now. May be unbound. Non null.
      */
     public void tbnz(Register cmp, int uimm6, Label label) {
         assert NumUtil.isUnsignedNbit(6, uimm6);
@@ -1472,7 +1475,7 @@
      *
      * @param cmp general purpose register. May not be null, zero-register or stackpointer.
      * @param uimm6 Unsigned 6-bit bit index.
-     * @param label Can only handle 21-bit word-aligned offsets for now. May be unbound. Non null.
+     * @param label Can only handle 16-bit word-aligned offsets for now. May be unbound. Non null.
      */
     public void tbz(Register cmp, int uimm6, Label label) {
         assert NumUtil.isUnsignedNbit(6, uimm6);
@@ -1681,6 +1684,9 @@
                 int sizeEncoding = information & NumUtil.getNbitNumberInt(6);
                 int regEncoding = information >>> 6;
                 Register reg = AArch64.cpuRegisters.get(regEncoding);
+                if (!NumUtil.isSignedNbit(16, branchOffset)) {
+                    throw new BranchTargetOutOfBoundsException(true, "Branch target %d out of bounds", branchOffset);
+                }
                 switch (type) {
                     case BRANCH_BIT_NONZERO:
                         super.tbnz(reg, sizeEncoding, branchOffset, branch);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java	Tue Mar 12 19:17:42 2019 +0100
@@ -683,7 +683,7 @@
             emitImmediate(asm, size, imm);
             int nextInsnPos = asm.position();
             if (annotateImm && asm.codePatchingAnnotationConsumer != null) {
-                asm.codePatchingAnnotationConsumer.accept(new ImmediateOperandAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos));
+                asm.codePatchingAnnotationConsumer.accept(new OperandDataAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos));
             }
         }
 
@@ -700,7 +700,7 @@
             emitImmediate(asm, size, imm);
             int nextInsnPos = asm.position();
             if (annotateImm && asm.codePatchingAnnotationConsumer != null) {
-                asm.codePatchingAnnotationConsumer.accept(new ImmediateOperandAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos));
+                asm.codePatchingAnnotationConsumer.accept(new OperandDataAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos));
             }
         }
     }
@@ -2023,7 +2023,7 @@
         emitInt(imm32);
         int nextInsnPos = position();
         if (annotateImm && codePatchingAnnotationConsumer != null) {
-            codePatchingAnnotationConsumer.accept(new ImmediateOperandAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos));
+            codePatchingAnnotationConsumer.accept(new OperandDataAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos));
         }
     }
 
@@ -2201,10 +2201,11 @@
     }
 
     public final void movswl(Register dst, AMD64Address src) {
-        prefix(src, dst);
-        emitByte(0x0F);
-        emitByte(0xBF);
-        emitOperandHelper(dst, src, 0);
+        AMD64RMOp.MOVSX.emit(this, DWORD, dst, src);
+    }
+
+    public final void movswq(Register dst, AMD64Address src) {
+        AMD64RMOp.MOVSX.emit(this, QWORD, dst, src);
     }
 
     public final void movw(AMD64Address dst, int imm16) {
@@ -2222,6 +2223,13 @@
         emitOperandHelper(src, dst, 0);
     }
 
+    public final void movw(Register dst, AMD64Address src) {
+        emitByte(0x66);
+        prefix(src, dst);
+        emitByte(0x8B);
+        emitOperandHelper(dst, src, 0);
+    }
+
     public final void movzbl(Register dst, AMD64Address src) {
         prefix(src, dst);
         emitByte(0x0F);
@@ -2237,11 +2245,16 @@
         AMD64RMOp.MOVZXB.emit(this, QWORD, dst, src);
     }
 
+    public final void movzbq(Register dst, AMD64Address src) {
+        AMD64RMOp.MOVZXB.emit(this, QWORD, dst, src);
+    }
+
     public final void movzwl(Register dst, AMD64Address src) {
-        prefix(src, dst);
-        emitByte(0x0F);
-        emitByte(0xB7);
-        emitOperandHelper(dst, src, 0);
+        AMD64RMOp.MOVZX.emit(this, DWORD, dst, src);
+    }
+
+    public final void movzwq(Register dst, AMD64Address src) {
+        AMD64RMOp.MOVZX.emit(this, QWORD, dst, src);
     }
 
     public final void negl(Register dst) {
@@ -2557,16 +2570,63 @@
         emitModRM(dst, src);
     }
 
-    // Insn: VPMOVZXBW xmm1, xmm2/m64
-
-    public final void pmovzxbw(Register dst, AMD64Address src) {
+    private void pmovSZx(Register dst, AMD64Address src, int op) {
         assert supports(CPUFeature.SSE4_1);
         assert inRC(XMM, dst);
         simdPrefix(dst, Register.None, src, PD, P_0F38, false);
-        emitByte(0x30);
+        emitByte(op);
         emitOperandHelper(dst, src, 0);
     }
 
+    public final void pmovsxbw(Register dst, AMD64Address src) {
+        pmovSZx(dst, src, 0x20);
+    }
+
+    public final void pmovsxbd(Register dst, AMD64Address src) {
+        pmovSZx(dst, src, 0x21);
+    }
+
+    public final void pmovsxbq(Register dst, AMD64Address src) {
+        pmovSZx(dst, src, 0x22);
+    }
+
+    public final void pmovsxwd(Register dst, AMD64Address src) {
+        pmovSZx(dst, src, 0x23);
+    }
+
+    public final void pmovsxwq(Register dst, AMD64Address src) {
+        pmovSZx(dst, src, 0x24);
+    }
+
+    public final void pmovsxdq(Register dst, AMD64Address src) {
+        pmovSZx(dst, src, 0x25);
+    }
+
+    // Insn: VPMOVZXBW xmm1, xmm2/m64
+    public final void pmovzxbw(Register dst, AMD64Address src) {
+        pmovSZx(dst, src, 0x30);
+    }
+
+    public final void pmovzxbd(Register dst, AMD64Address src) {
+        pmovSZx(dst, src, 0x31);
+    }
+
+    public final void pmovzxbq(Register dst, AMD64Address src) {
+        pmovSZx(dst, src, 0x32);
+    }
+
+    public final void pmovzxwd(Register dst, AMD64Address src) {
+        pmovSZx(dst, src, 0x33);
+    }
+
+    public final void pmovzxwq(Register dst, AMD64Address src) {
+        pmovSZx(dst, src, 0x34);
+    }
+
+    public final void pmovzxdq(Register dst, AMD64Address src) {
+        pmovSZx(dst, src, 0x35);
+    }
+
     public final void pmovzxbw(Register dst, Register src) {
         assert supports(CPUFeature.SSE4_1);
         assert inRC(XMM, dst) && inRC(XMM, src);
@@ -2881,6 +2941,10 @@
         XOR.rmOp.emit(this, DWORD, dst, src);
     }
 
+    public final void xorq(Register dst, Register src) {
+        XOR.rmOp.emit(this, QWORD, dst, src);
+    }
+
     public final void xorpd(Register dst, Register src) {
         SSEOp.XOR.emit(this, PD, dst, src);
     }
@@ -3045,7 +3109,7 @@
         emitLong(imm64);
         int nextInsnPos = position();
         if (annotateImm && codePatchingAnnotationConsumer != null) {
-            codePatchingAnnotationConsumer.accept(new ImmediateOperandAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos));
+            codePatchingAnnotationConsumer.accept(new OperandDataAnnotation(insnPos, immPos, nextInsnPos - immPos, nextInsnPos));
         }
     }
 
@@ -3189,6 +3253,19 @@
         emitModRM(5, dst);
     }
 
+    public final void sarq(Register dst, int imm8) {
+        assert isShiftCount(imm8 >> 1) : "illegal shift count";
+        prefixq(dst);
+        if (imm8 == 1) {
+            emitByte(0xD1);
+            emitModRM(7, dst);
+        } else {
+            emitByte(0xC1);
+            emitModRM(7, dst);
+            emitByte(imm8);
+        }
+    }
+
     public final void sbbq(Register dst, Register src) {
         SBB.rmOp.emit(this, QWORD, dst, src);
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64BaseAssembler.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64BaseAssembler.java	Tue Mar 12 19:17:42 2019 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -210,7 +210,7 @@
         }
     }
 
-    public abstract static class OperandDataAnnotation extends CodeAnnotation {
+    public static class OperandDataAnnotation extends CodeAnnotation {
         /**
          * The position (bytes from the beginning of the method) of the operand.
          */
@@ -239,30 +239,10 @@
         }
     }
 
-    /**
-     * Annotation that stores additional information about the displacement of a
-     * {@link Assembler#getPlaceholder placeholder address} that needs patching.
-     */
-    protected static class AddressDisplacementAnnotation extends OperandDataAnnotation {
-        AddressDisplacementAnnotation(int instructionPosition, int operandPosition, int operandSize, int nextInstructionPosition) {
-            super(instructionPosition, operandPosition, operandSize, nextInstructionPosition);
-        }
-    }
-
-    /**
-     * Annotation that stores additional information about the immediate operand, e.g., of a call
-     * instruction, that needs patching.
-     */
-    protected static class ImmediateOperandAnnotation extends OperandDataAnnotation {
-        ImmediateOperandAnnotation(int instructionPosition, int operandPosition, int operandSize, int nextInstructionPosition) {
-            super(instructionPosition, operandPosition, operandSize, nextInstructionPosition);
-        }
-    }
-
     protected void annotatePatchingImmediate(int operandOffset, int operandSize) {
         if (codePatchingAnnotationConsumer != null) {
             int pos = position();
-            codePatchingAnnotationConsumer.accept(new ImmediateOperandAnnotation(pos, pos + operandOffset, operandSize, pos + operandOffset + operandSize));
+            codePatchingAnnotationConsumer.accept(new OperandDataAnnotation(pos, pos + operandOffset, operandSize, pos + operandOffset + operandSize));
         }
     }
 
@@ -581,7 +561,7 @@
             assert index.equals(Register.None) : "cannot use RIP relative addressing with index register";
             emitByte(0x05 | regenc);
             if (codePatchingAnnotationConsumer != null && addr.instructionStartPosition >= 0) {
-                codePatchingAnnotationConsumer.accept(new AddressDisplacementAnnotation(addr.instructionStartPosition, position(), 4, position() + 4 + additionalInstructionSize));
+                codePatchingAnnotationConsumer.accept(new OperandDataAnnotation(addr.instructionStartPosition, position(), 4, position() + 4 + additionalInstructionSize));
             }
             emitInt(disp);
         } else if (base.isValid()) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCAssembler.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCAssembler.java	Tue Mar 12 19:17:42 2019 +0100
@@ -136,9 +136,9 @@
 import java.util.Map;
 
 import org.graalvm.compiler.asm.Assembler;
+import org.graalvm.compiler.asm.BranchTargetOutOfBoundsException;
 import org.graalvm.compiler.asm.Label;
 import org.graalvm.compiler.core.common.NumUtil;
-import org.graalvm.compiler.core.common.PermanentBailoutException;
 import org.graalvm.compiler.debug.GraalError;
 
 import jdk.vm.ci.code.Register;
@@ -1281,7 +1281,7 @@
         public int setDisp(int inst, int d) {
             assert this.match(inst);
             if (!isValidDisp(d)) {
-                throw new PermanentBailoutException("Too large displacement 0x%x in field %s in instruction %s", d, this.disp, this);
+                throw new BranchTargetOutOfBoundsException(true, "Too large displacement 0x%x in field %s in instruction %s", d, this.disp, this);
             }
             return this.disp.setBits(inst, d);
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.test/src/org/graalvm/compiler/asm/test/AssemblerTest.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.test/src/org/graalvm/compiler/asm/test/AssemblerTest.java	Tue Mar 12 19:17:42 2019 +0100
@@ -32,6 +32,7 @@
 import org.graalvm.compiler.code.CompilationResult;
 import org.graalvm.compiler.code.DisassemblerProvider;
 import org.graalvm.compiler.core.common.CompilationIdentifier;
+import org.graalvm.compiler.core.gen.LIRGenerationProvider;
 import org.graalvm.compiler.core.target.Backend;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.nodes.StructuredGraph;
@@ -90,7 +91,7 @@
             RegisterConfig registerConfig = codeCache.getRegisterConfig();
             CompilationIdentifier compilationId = backend.getCompilationIdentifier(method);
             StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(method).compilationId(compilationId).build();
-            CallingConvention cc = backend.newLIRGenerationResult(compilationId, null, null, graph, null).getCallingConvention();
+            CallingConvention cc = ((LIRGenerationProvider) backend).newLIRGenerationResult(compilationId, null, null, graph, null).getCallingConvention();
 
             CompilationResult compResult = new CompilationResult(graph.compilationId());
             byte[] targetCode = test.generateCode(compResult, codeCache.getTarget(), registerConfig, cc);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/BranchTargetOutOfBoundsException.java	Tue Mar 12 19:17:42 2019 +0100
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 org.graalvm.compiler.asm;
+
+import org.graalvm.compiler.core.common.GraalBailoutException;
+
+@SuppressWarnings("serial")
+public class BranchTargetOutOfBoundsException extends GraalBailoutException {
+
+    public BranchTargetOutOfBoundsException(boolean permanent, String format, Object... args) {
+        super(permanent, format, args);
+    }
+
+    public BranchTargetOutOfBoundsException(String format, Object... args) {
+        super(format, args);
+    }
+
+    public BranchTargetOutOfBoundsException(Throwable cause, String format, Object... args) {
+        super(cause, format, args);
+    }
+
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java	Tue Mar 12 19:17:42 2019 +0100
@@ -55,6 +55,7 @@
 import jdk.vm.ci.meta.InvokeTarget;
 import jdk.vm.ci.meta.ResolvedJavaField;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.SpeculationLog;
 
 /**
  * Represents the output from compiling a method, including the compiled machine code, associated
@@ -221,6 +222,11 @@
     private ResolvedJavaMethod[] methods;
 
     /**
+     * The {@link SpeculationLog} log used during compilation.
+     */
+    private SpeculationLog speculationLog;
+
+    /**
      * The list of fields that were accessed from the bytecodes.
      */
     private ResolvedJavaField[] fields;
@@ -373,6 +379,21 @@
     }
 
     /**
+     * Sets the {@link SpeculationLog} log used during compilation.
+     */
+    public void setSpeculationLog(SpeculationLog speculationLog) {
+        checkOpen();
+        this.speculationLog = speculationLog;
+    }
+
+    /**
+     * Gets the {@link SpeculationLog} log, if any, used during compilation.
+     */
+    public SpeculationLog getSpeculationLog() {
+        return speculationLog;
+    }
+
+    /**
      * Sets the fields that were referenced from the bytecodes that were used as input to the
      * compilation.
      *
@@ -615,7 +636,7 @@
     /**
      * @return the code annotations or {@code null} if there are none
      */
-    public List<CodeAnnotation> getAnnotations() {
+    public List<CodeAnnotation> getCodeAnnotations() {
         if (annotations == null) {
             return Collections.emptyList();
         }
@@ -706,7 +727,8 @@
      * Clears the information in this object pertaining to generating code. That is, the
      * {@linkplain #getMarks() marks}, {@linkplain #getInfopoints() infopoints},
      * {@linkplain #getExceptionHandlers() exception handlers}, {@linkplain #getDataPatches() data
-     * patches} and {@linkplain #getAnnotations() annotations} recorded in this object are cleared.
+     * patches} and {@linkplain #getCodeAnnotations() annotations} recorded in this object are
+     * cleared.
      */
     public void resetForEmittingCode() {
         checkOpen();
@@ -721,6 +743,14 @@
         }
     }
 
+    public void clearInfopoints() {
+        infopoints.clear();
+    }
+
+    public void clearExceptionHandlers() {
+        exceptionHandlers.clear();
+    }
+
     private void checkOpen() {
         if (closed) {
             throw new IllegalStateException();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/HexCodeFileDisassemblerProvider.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/HexCodeFileDisassemblerProvider.java	Tue Mar 12 19:17:42 2019 +0100
@@ -78,7 +78,7 @@
         long start = installedCode == null ? 0L : installedCode.getStart();
         HexCodeFile hcf = new HexCodeFile(code, start, target.arch.getName(), target.wordSize * 8);
         if (compResult != null) {
-            HexCodeFile.addAnnotations(hcf, compResult.getAnnotations());
+            HexCodeFile.addAnnotations(hcf, compResult.getCodeAnnotations());
             addExceptionHandlersComment(compResult, hcf);
             Register fp = regConfig.getFrameRegister();
             RefMapFormatter slotFormatter = new DefaultRefMapFormatter(target.wordSize, fp, 0);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64CbzTest.java	Tue Mar 12 19:17:42 2019 +0100
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+
+package org.graalvm.compiler.core.aarch64.test;
+
+import org.graalvm.compiler.lir.LIRInstruction;
+import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow;
+import org.junit.Test;
+
+import java.util.function.Predicate;
+
+public class AArch64CbzTest extends AArch64MatchRuleTest {
+    private static final Predicate<LIRInstruction> predicate = op -> (op instanceof AArch64ControlFlow.CompareBranchZeroOp);
+
+    public static int equalsTo(int x) {
+        if (x == 0) {
+            return 1;
+        } else {
+            return x - 1;
+        }
+    }
+
+    public static int notEqualsTo(int x) {
+        if (x != 0) {
+            return x + 2;
+        } else {
+            return 3;
+        }
+    }
+
+    public static String isNull(String s) {
+        if (s == null) {
+            return "abc";
+        } else {
+            return s + "abc";
+        }
+    }
+
+    public static String isNotNull(String s) {
+        if (s != null) {
+            return s + "abc";
+        } else {
+            return "abc";
+        }
+    }
+
+    public static String objectEqualsNull(String s1, String s2) {
+        if (s1.equals(null)) {
+            return s1 + "abc";
+        } else {
+            return s2 + "abd";
+        }
+    }
+
+    public static String objectEquals(String s1, String s2) {
+        if (s1.equals(s2)) {
+            return s1 + "abc";
+        } else {
+            return s2 + "abd";
+        }
+    }
+
+    @Test
+    public void testEqualsTo() {
+        test("equalsTo", 0);
+        test("equalsTo", 1);
+        checkLIR("equalsTo", predicate, 1);
+    }
+
+    @Test
+    public void testNotEqualsTo() {
+        test("notEqualsTo", 0);
+        test("notEqualsTo", 1);
+        checkLIR("notEqualsTo", predicate, 1);
+    }
+
+    @Test
+    public void testIsNull() {
+        test("isNull", new Object[]{null});
+        test("isNull", "abc");
+        checkLIR("isNull", predicate, 1);
+    }
+
+    @Test
+    public void testIsNotNull() {
+        test("isNotNull", new Object[]{null});
+        test("isNotNull", "abc");
+        checkLIR("isNotNull", predicate, 1);
+    }
+
+    @Test
+    public void testObjectEqualsNull() {
+        test("objectEqualsNull", "ab", "ac");
+        test("objectEqualsNull", "abc", "abc");
+        checkLIR("objectEqualsNull", predicate, 1);
+    }
+
+    @Test
+    public void testObjectEquals() {
+        test("objectEquals", "ab", "ac");
+        test("objectEquals", "abc", "abc");
+        checkLIR("objectEquals", predicate, 0);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64MembarOpTest.java	Tue Mar 12 19:17:42 2019 +0100
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package org.graalvm.compiler.core.aarch64.test;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assume.assumeTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import jdk.internal.vm.compiler.collections.Pair;
+import org.graalvm.compiler.asm.aarch64.AArch64Assembler.BarrierKind;
+import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
+import org.graalvm.compiler.code.CompilationResult;
+import org.graalvm.compiler.core.gen.LIRGenerationProvider;
+import org.graalvm.compiler.core.test.backend.BackendTest;
+import org.graalvm.compiler.lir.aarch64.AArch64Move.MembarOp;
+import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
+import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory;
+import org.graalvm.compiler.lir.gen.LIRGenerationResult;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.junit.Before;
+import org.junit.Test;
+
+import jdk.vm.ci.aarch64.AArch64;
+import jdk.vm.ci.code.MemoryBarriers;
+import jdk.vm.ci.runtime.JVMCI;
+import jdk.vm.ci.runtime.JVMCIBackend;
+
+public class AArch64MembarOpTest extends BackendTest {
+
+    private final JVMCIBackend providers;
+    private final CompilationResultBuilder crb;
+
+    public AArch64MembarOpTest() {
+        this.providers = JVMCI.getRuntime().getHostJVMCIBackend();
+
+        final StructuredGraph graph = parseEager("stub", StructuredGraph.AllowAssumptions.YES);
+        LIRGenerationResult lirGenRes = getLIRGenerationResult(graph);
+        CompilationResult compResult = new CompilationResult(graph.compilationId());
+        this.crb = ((LIRGenerationProvider) getBackend()).newCompilationResultBuilder(lirGenRes, lirGenRes.getFrameMap(), compResult, CompilationResultBuilderFactory.Default);
+    }
+
+    public void stub() {
+    }
+
+    @Before
+    public void checkAArch64() {
+        assumeTrue("skipping AArch64 specific test", JVMCI.getRuntime().getHostJVMCIBackend().getTarget().arch instanceof AArch64);
+    }
+
+    @Test
+    public void runNormalMembarTests() {
+        List<Pair<Integer, BarrierKind>> cases = new ArrayList<>();
+        cases.add(Pair.create(MemoryBarriers.LOAD_LOAD, BarrierKind.LOAD_LOAD));
+        cases.add(Pair.create(MemoryBarriers.LOAD_STORE, BarrierKind.LOAD_LOAD));
+        cases.add(Pair.create(MemoryBarriers.LOAD_LOAD | MemoryBarriers.LOAD_STORE, BarrierKind.LOAD_LOAD));
+        cases.add(Pair.create(MemoryBarriers.STORE_LOAD, BarrierKind.ANY_ANY));
+        cases.add(Pair.create(MemoryBarriers.STORE_LOAD | MemoryBarriers.LOAD_LOAD, BarrierKind.ANY_ANY));
+        cases.add(Pair.create(MemoryBarriers.STORE_LOAD | MemoryBarriers.LOAD_STORE, BarrierKind.ANY_ANY));
+        cases.add(Pair.create(MemoryBarriers.STORE_LOAD | MemoryBarriers.LOAD_LOAD | MemoryBarriers.LOAD_STORE, BarrierKind.ANY_ANY));
+        cases.add(Pair.create(MemoryBarriers.STORE_STORE, BarrierKind.STORE_STORE));
+        cases.add(Pair.create(MemoryBarriers.STORE_STORE | MemoryBarriers.LOAD_LOAD, BarrierKind.ANY_ANY));
+        cases.add(Pair.create(MemoryBarriers.STORE_STORE | MemoryBarriers.LOAD_STORE, BarrierKind.ANY_ANY));
+        cases.add(Pair.create(MemoryBarriers.STORE_STORE | MemoryBarriers.LOAD_LOAD | MemoryBarriers.LOAD_STORE, BarrierKind.ANY_ANY));
+        cases.add(Pair.create(MemoryBarriers.STORE_STORE | MemoryBarriers.STORE_LOAD, BarrierKind.ANY_ANY));
+        cases.add(Pair.create(MemoryBarriers.STORE_STORE | MemoryBarriers.STORE_LOAD | MemoryBarriers.LOAD_LOAD, BarrierKind.ANY_ANY));
+        cases.add(Pair.create(MemoryBarriers.STORE_STORE | MemoryBarriers.STORE_LOAD | MemoryBarriers.LOAD_STORE, BarrierKind.ANY_ANY));
+        cases.add(Pair.create(MemoryBarriers.STORE_STORE | MemoryBarriers.STORE_LOAD | MemoryBarriers.LOAD_STORE | MemoryBarriers.LOAD_LOAD, BarrierKind.ANY_ANY));
+
+        for (Pair<Integer, BarrierKind> c : cases) {
+            assertArrayEquals(new MembarOpActual(c.getLeft()).emit(new AArch64MacroAssembler(providers.getTarget())),
+                            new MembarOpExpected(c.getRight()).emit(new AArch64MacroAssembler(providers.getTarget())));
+        }
+    }
+
+    @Test(expected = AssertionError.class)
+    public void runExceptionalTests() {
+        new MembarOpActual(16).emit(new AArch64MacroAssembler(providers.getTarget()));
+    }
+
+    private class MembarOpActual {
+        private MembarOp op;
+
+        MembarOpActual(int barriers) {
+            op = new MembarOp(barriers);
+        }
+
+        byte[] emit(AArch64MacroAssembler masm) {
+            op.emitCode(crb, masm);
+            return masm.close(false);
+        }
+    }
+
+    private class MembarOpExpected {
+        private BarrierKind barrierKind;
+
+        MembarOpExpected(BarrierKind barrierKind) {
+            this.barrierKind = barrierKind;
+        }
+
+        byte[] emit(AArch64MacroAssembler masm) {
+            masm.dmb(barrierKind);
+            return masm.close(false);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64TestBitAndBranchTest.java	Tue Mar 12 19:17:42 2019 +0100
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 org.graalvm.compiler.core.aarch64.test;
+
+import static org.junit.Assume.assumeTrue;
+
+import java.util.function.Predicate;
+
+import org.graalvm.compiler.api.directives.GraalDirectives;
+import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
+import org.graalvm.compiler.lir.LIR;
+import org.graalvm.compiler.lir.LIRInstruction;
+import org.graalvm.compiler.lir.LIRInstructionClass;
+import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow;
+import org.graalvm.compiler.lir.aarch64.AArch64LIRInstruction;
+import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
+import org.graalvm.compiler.lir.gen.LIRGenerationResult;
+import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
+import org.graalvm.compiler.lir.jtt.LIRTest;
+import org.graalvm.compiler.lir.jtt.LIRTestSpecification;
+import org.graalvm.compiler.lir.phases.LIRPhase;
+import org.graalvm.compiler.lir.phases.LIRSuites;
+import org.graalvm.compiler.lir.phases.PreAllocationOptimizationPhase.PreAllocationOptimizationContext;
+import org.graalvm.compiler.options.OptionValues;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import jdk.vm.ci.aarch64.AArch64;
+import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.meta.Value;
+
+public class AArch64TestBitAndBranchTest extends LIRTest {
+    private static final Predicate<LIRInstruction> checkForBitTestAndBranchOp = op -> (op instanceof AArch64ControlFlow.BitTestAndBranchOp);
+    private LIR lir;
+
+    @Before
+    public void checkAArch64() {
+        assumeTrue("skipping AArch64 specific test", getTarget().arch instanceof AArch64);
+    }
+
+    public static long testBit42Snippet(long a, long b, long c) {
+        if ((a & (1 << 42)) == 0) {
+            return b;
+        } else {
+            return c;
+        }
+    }
+
+    @Test
+    public void testBit42() {
+        test("testBit42Snippet", 1L << 42L, Long.MAX_VALUE, Long.MIN_VALUE);
+        test("testBit42Snippet", ~(1L << 42L), Long.MAX_VALUE, Long.MIN_VALUE);
+        checkLIR("testBit42Snippet", checkForBitTestAndBranchOp, 1);
+    }
+
+    private static final LargeOpSpec largeOpSingleNop = new LargeOpSpec((1 << 14 - 2), 2);
+
+    /**
+     * Tests the graceful case, where the estimation for
+     * {@link CompilationResultBuilder#labelWithinRange(LIRInstruction, org.graalvm.compiler.asm.Label, int)}
+     * holds.
+     */
+    public static int testBitTestAndBranchSingleSnippet(int a) {
+        int res;
+        if (a % 2 == 0) {
+            res = fillOps(largeOpSingleNop, 1);
+        } else {
+            res = fillOps(largeOpSingleNop, 2);
+        }
+        return GraalDirectives.opaque(res);
+    }
+
+    @Test
+    public void testBitTestAndBranchSingle() {
+        runTest("testBitTestAndBranchSingleSnippet", 1);
+        checkLIR("testBitTestAndBranchSingleSnippet", checkForBitTestAndBranchOp, 1);
+    }
+
+    private static final LargeOpSpec largeOpFourNop = new LargeOpSpec((1 << 14 - 2), 8);
+
+    /**
+     * Tests the case, where the estimation for
+     * {@link CompilationResultBuilder#labelWithinRange(LIRInstruction, org.graalvm.compiler.asm.Label, int)}
+     * does not hold and the code generation must be redone with large branches.
+     */
+    public static int testBitTestAndBranchFourSnippet(int a) {
+        int res;
+        if (a % 2 == 0) {
+            res = fillOps(largeOpFourNop, 1);
+        } else {
+            res = fillOps(largeOpFourNop, 2);
+        }
+        return GraalDirectives.opaque(res);
+    }
+
+    @Test
+    public void testBitTestAndBranchFour() {
+        runTest("testBitTestAndBranchFourSnippet", 1);
+        checkLIR("testBitTestAndBranchFourSnippet", checkForBitTestAndBranchOp, 1);
+    }
+
+    private static class LargeOpSpec extends LIRTestSpecification {
+        private final int n;
+        private final int nopCount;
+
+        LargeOpSpec(int n, int nopCount) {
+            super();
+            this.n = n;
+            this.nopCount = nopCount;
+        }
+
+        @Override
+        public void generate(LIRGeneratorTool gen, Value a) {
+            for (int i = 0; i < n; i++) {
+                gen.append(new NoOp(nopCount));
+            }
+            setResult(a);
+        }
+    }
+
+    public static class NoOp extends AArch64LIRInstruction {
+        private static final LIRInstructionClass<NoOp> TYPE = LIRInstructionClass.create(NoOp.class);
+        private final int nopCount;
+
+        public NoOp(int nopCount) {
+            super(TYPE);
+            this.nopCount = nopCount;
+        }
+
+        @Override
+        protected void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
+            for (int i = 0; i < nopCount; i++) {
+                masm.nop();
+            }
+        }
+    }
+
+    @LIRIntrinsic
+    public static int fillOps(@SuppressWarnings("unused") LargeOpSpec s, int a) {
+        return a;
+    }
+
+    @Override
+    protected LIRSuites createLIRSuites(OptionValues options) {
+        LIRSuites suites = super.createLIRSuites(options);
+        suites.getPreAllocationOptimizationStage().appendPhase(new CheckPhase());
+        return suites;
+    }
+
+    public class CheckPhase extends LIRPhase<PreAllocationOptimizationContext> {
+        @Override
+        protected void run(TargetDescription target, LIRGenerationResult lirGenRes, PreAllocationOptimizationContext context) {
+            lir = lirGenRes.getLIR();
+        }
+    }
+
+    protected void checkLIR(String methodName, Predicate<LIRInstruction> predicate, int expected) {
+        compile(getResolvedJavaMethod(methodName), null);
+        int actualOpNum = 0;
+        for (LIRInstruction ins : lir.getLIRforBlock(lir.codeEmittingOrder()[0])) {
+            if (predicate.test(ins)) {
+                actualOpNum++;
+            }
+        }
+        Assert.assertEquals(expected, actualOpNum);
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java	Tue Mar 12 19:17:42 2019 +0100
@@ -485,26 +485,6 @@
     }
 
     @Override
-    public Value emitMathLog(Value input, boolean base10) {
-        throw GraalError.unimplemented();
-    }
-
-    @Override
-    public Value emitMathCos(Value input) {
-        throw GraalError.unimplemented();
-    }
-
-    @Override
-    public Value emitMathSin(Value input) {
-        throw GraalError.unimplemented();
-    }
-
-    @Override
-    public Value emitMathTan(Value input) {
-        throw GraalError.unimplemented();
-    }
-
-    @Override
     public void emitCompareOp(AArch64Kind cmpKind, Variable left, Value right) {
         throw GraalError.unimplemented();
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRGenerator.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRGenerator.java	Tue Mar 12 19:17:42 2019 +0100
@@ -52,6 +52,7 @@
 import org.graalvm.compiler.lir.aarch64.AArch64Compare;
 import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow;
 import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.BranchOp;
+import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.CompareBranchZeroOp;
 import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.CondMoveOp;
 import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.CondSetOp;
 import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.StrategySwitchOp;
@@ -257,6 +258,27 @@
     @Override
     public void emitCompareBranch(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination,
                     double trueDestinationProbability) {
+        if (cond == Condition.EQ) {
+            // emit cbz instruction for IsNullNode.
+            assert !LIRValueUtil.isNullConstant(left) : "emitNullCheckBranch()'s null input should be in right.";
+            if (LIRValueUtil.isNullConstant(right)) {
+                append(new CompareBranchZeroOp(asAllocatable(left), trueDestination, falseDestination, trueDestinationProbability));
+                return;
+            }
+
+            // emit cbz instruction for IntegerEquals when any of the inputs is zero.
+            AArch64Kind kind = (AArch64Kind) cmpKind;
+            if (kind.isInteger()) {
+                if (isIntConstant(left, 0)) {
+                    append(new CompareBranchZeroOp(asAllocatable(right), trueDestination, falseDestination, trueDestinationProbability));
+                    return;
+                } else if (isIntConstant(right, 0)) {
+                    append(new CompareBranchZeroOp(asAllocatable(left), trueDestination, falseDestination, trueDestinationProbability));
+                    return;
+                }
+            }
+        }
+
         boolean mirrored = emitCompare(cmpKind, left, right, cond, unorderedIsTrue);
         Condition finalCondition = mirrored ? cond.mirror() : cond;
         boolean finalUnorderedIsTrue = mirrored ? !unorderedIsTrue : unorderedIsTrue;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java	Tue Mar 12 19:17:42 2019 +0100
@@ -37,11 +37,14 @@
 import org.graalvm.compiler.core.match.MatchRule;
 import org.graalvm.compiler.graph.Node;
 import org.graalvm.compiler.lir.LIRFrameState;
+import org.graalvm.compiler.lir.LabelRef;
 import org.graalvm.compiler.lir.Variable;
 import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp;
+import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow;
 import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
 import org.graalvm.compiler.nodes.ConstantNode;
 import org.graalvm.compiler.nodes.DeoptimizingNode;
+import org.graalvm.compiler.nodes.IfNode;
 import org.graalvm.compiler.nodes.NodeView;
 import org.graalvm.compiler.nodes.ValueNode;
 import org.graalvm.compiler.nodes.calc.AddNode;
@@ -178,6 +181,28 @@
         return builder -> getArithmeticLIRGenerator().emitMSub(operand(a), operand(b), operand(c));
     }
 
+    /**
+     * ((x & (1 << n)) == 0) -> tbz/tbnz n label.
+     */
+    @MatchRule("(If (IntegerTest value Constant=a))")
+    public ComplexMatchResult testBitAndBranch(IfNode root, ValueNode value, ConstantNode a) {
+        if (value.getStackKind().isNumericInteger()) {
+            long constant = a.asJavaConstant().asLong();
+            if (Long.bitCount(constant) == 1) {
+                int bitToTest = Long.numberOfTrailingZeros(constant);
+                return builder -> {
+                    LabelRef trueDestination = getLIRBlock(root.trueSuccessor());
+                    LabelRef falseDestination = getLIRBlock(root.falseSuccessor());
+                    AllocatableValue src = moveSp(gen.asAllocatable(operand(value)));
+                    double trueDestinationProbability = root.getTrueSuccessorProbability();
+                    gen.append(new AArch64ControlFlow.BitTestAndBranchOp(trueDestination, falseDestination, src, trueDestinationProbability, bitToTest));
+                    return null;
+                };
+            }
+        }
+        return null;
+    }
+
     @Override
     public AArch64LIRGenerator getLIRGeneratorTool() {
         return (AArch64LIRGenerator) gen;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java	Tue Mar 12 19:17:42 2019 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -80,13 +80,6 @@
 import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant;
 import static org.graalvm.compiler.lir.amd64.AMD64Arithmetic.DREM;
 import static org.graalvm.compiler.lir.amd64.AMD64Arithmetic.FREM;
-import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicBinaryOp.BinaryIntrinsicOpcode.POW;
-import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp.UnaryIntrinsicOpcode.COS;
-import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp.UnaryIntrinsicOpcode.EXP;
-import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp.UnaryIntrinsicOpcode.LOG;
-import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp.UnaryIntrinsicOpcode.LOG10;
-import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp.UnaryIntrinsicOpcode.SIN;
-import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp.UnaryIntrinsicOpcode.TAN;
 
 import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic;
 import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp;
@@ -116,8 +109,13 @@
 import org.graalvm.compiler.lir.amd64.AMD64Binary;
 import org.graalvm.compiler.lir.amd64.AMD64BinaryConsumer;
 import org.graalvm.compiler.lir.amd64.AMD64ClearRegisterOp;
-import org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicBinaryOp;
-import org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp;
+import org.graalvm.compiler.lir.amd64.AMD64MathCosOp;
+import org.graalvm.compiler.lir.amd64.AMD64MathExpOp;
+import org.graalvm.compiler.lir.amd64.AMD64MathLog10Op;
+import org.graalvm.compiler.lir.amd64.AMD64MathLogOp;
+import org.graalvm.compiler.lir.amd64.AMD64MathPowOp;
+import org.graalvm.compiler.lir.amd64.AMD64MathSinOp;
+import org.graalvm.compiler.lir.amd64.AMD64MathTanOp;
 import org.graalvm.compiler.lir.amd64.AMD64Move;
 import org.graalvm.compiler.lir.amd64.AMD64MulDivOp;
 import org.graalvm.compiler.lir.amd64.AMD64ShiftOp;
@@ -127,7 +125,6 @@
 import org.graalvm.compiler.lir.amd64.vector.AMD64VectorBinary.AVXBinaryOp;
 import org.graalvm.compiler.lir.amd64.vector.AMD64VectorUnary;
 import org.graalvm.compiler.lir.gen.ArithmeticLIRGenerator;
-import org.graalvm.compiler.lir.gen.LIRGenerator;
 
 import jdk.vm.ci.amd64.AMD64;
 import jdk.vm.ci.amd64.AMD64.CPUFeature;
@@ -152,41 +149,11 @@
 
     private static final RegisterValue RCX_I = AMD64.rcx.asValue(LIRKind.value(AMD64Kind.DWORD));
 
-    public AMD64ArithmeticLIRGenerator(AllocatableValue nullRegisterValue, Maths maths) {
+    public AMD64ArithmeticLIRGenerator(AllocatableValue nullRegisterValue) {
         this.nullRegisterValue = nullRegisterValue;
-        this.maths = maths == null ? new Maths() {
-        } : maths;
     }
 
     private final AllocatableValue nullRegisterValue;
-    private final Maths maths;
-
-    /**
-     * Interface for emitting LIR for selected {@link Math} routines. A {@code null} return value
-     * for any method in this interface means the caller must emit the LIR itself.
-     */
-    public interface Maths {
-
-        @SuppressWarnings("unused")
-        default Variable emitLog(LIRGenerator gen, Value input, boolean base10) {
-            return null;
-        }
-
-        @SuppressWarnings("unused")
-        default Variable emitCos(LIRGenerator gen, Value input) {
-            return null;
-        }
-
-        @SuppressWarnings("unused")
-        default Variable emitSin(LIRGenerator gen, Value input) {
-            return null;
-        }
-
-        @SuppressWarnings("unused")
-        default Variable emitTan(LIRGenerator gen, Value input) {
-            return null;
-        }
-    }
 
     @Override
     public Variable emitNegate(Value inputVal) {
@@ -781,6 +748,7 @@
         }
     }
 
+    @Override
     public Variable emitRor(Value a, Value b) {
         switch ((AMD64Kind) a.getPlatformKind()) {
             case DWORD:
@@ -1103,65 +1071,36 @@
 
     @Override
     public Value emitMathLog(Value input, boolean base10) {
-        LIRGenerator gen = getLIRGen();
-        Variable result = maths.emitLog(gen, input, base10);
-        if (result == null) {
-            result = gen.newVariable(LIRKind.combine(input));
-            AllocatableValue stackSlot = gen.getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(AMD64Kind.QWORD));
-            gen.append(new AMD64MathIntrinsicUnaryOp(getAMD64LIRGen(), base10 ? LOG10 : LOG, result, asAllocatable(input), stackSlot));
+        if (base10) {
+            return new AMD64MathLog10Op().emitLIRWrapper(getLIRGen(), input);
+        } else {
+            return new AMD64MathLogOp().emitLIRWrapper(getLIRGen(), input);
         }
-        return result;
     }
 
     @Override
     public Value emitMathCos(Value input) {
-        LIRGenerator gen = getLIRGen();
-        Variable result = maths.emitCos(gen, input);
-        if (result == null) {
-            result = gen.newVariable(LIRKind.combine(input));
-            AllocatableValue stackSlot = gen.getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(AMD64Kind.QWORD));
-            gen.append(new AMD64MathIntrinsicUnaryOp(getAMD64LIRGen(), COS, result, asAllocatable(input), stackSlot));
-        }
-        return result;
+        return new AMD64MathCosOp().emitLIRWrapper(getLIRGen(), input);
     }
 
     @Override
     public Value emitMathSin(Value input) {
-        LIRGenerator gen = getLIRGen();
-        Variable result = maths.emitSin(gen, input);
-        if (result == null) {
-            result = gen.newVariable(LIRKind.combine(input));
-            AllocatableValue stackSlot = gen.getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(AMD64Kind.QWORD));
-            gen.append(new AMD64MathIntrinsicUnaryOp(getAMD64LIRGen(), SIN, result, asAllocatable(input), stackSlot));
-        }
-        return result;
+        return new AMD64MathSinOp().emitLIRWrapper(getLIRGen(), input);
     }
 
     @Override
     public Value emitMathTan(Value input) {
-        LIRGenerator gen = getLIRGen();
-        Variable result = maths.emitTan(gen, input);
-        if (result == null) {
-            result = gen.newVariable(LIRKind.combine(input));
-            AllocatableValue stackSlot = gen.getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(AMD64Kind.QWORD));
-            gen.append(new AMD64MathIntrinsicUnaryOp(getAMD64LIRGen(), TAN, result, asAllocatable(input), stackSlot));
-        }
-        return result;
+        return new AMD64MathTanOp().emitLIRWrapper(getLIRGen(), input);
     }
 
     @Override
     public Value emitMathExp(Value input) {
-        Variable result = getLIRGen().newVariable(LIRKind.combine(input));
-        AllocatableValue stackSlot = getLIRGen().getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(AMD64Kind.QWORD));
-        getLIRGen().append(new AMD64MathIntrinsicUnaryOp(getAMD64LIRGen(), EXP, result, asAllocatable(input), stackSlot));
-        return result;
+        return new AMD64MathExpOp().emitLIRWrapper(getLIRGen(), input);
     }
 
     @Override
-    public Value emitMathPow(Value input1, Value input2) {
-        Variable result = getLIRGen().newVariable(LIRKind.combine(input1));
-        getLIRGen().append(new AMD64MathIntrinsicBinaryOp(getAMD64LIRGen(), POW, result, asAllocatable(input1), asAllocatable(input2)));
-        return result;
+    public Value emitMathPow(Value x, Value y) {
+        return new AMD64MathPowOp().emitLIRWrapper(getLIRGen(), x, y);
     }
 
     protected AMD64LIRGenerator getAMD64LIRGen() {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java	Tue Mar 12 19:17:42 2019 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -41,6 +41,8 @@
 import static org.graalvm.compiler.lir.LIRValueUtil.isIntConstant;
 import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant;
 
+import java.util.Optional;
+
 import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic;
 import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp;
 import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp;
@@ -81,6 +83,7 @@
 import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.ReturnOp;
 import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.StrategySwitchOp;
 import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.TableSwitchOp;
+import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.HashTableSwitchOp;
 import org.graalvm.compiler.lir.amd64.AMD64LFenceOp;
 import org.graalvm.compiler.lir.amd64.AMD64Move;
 import org.graalvm.compiler.lir.amd64.AMD64Move.CompareAndSwapOp;
@@ -93,6 +96,7 @@
 import org.graalvm.compiler.lir.amd64.AMD64ZapStackOp;
 import org.graalvm.compiler.lir.gen.LIRGenerationResult;
 import org.graalvm.compiler.lir.gen.LIRGenerator;
+import org.graalvm.compiler.lir.hashing.Hasher;
 import org.graalvm.compiler.phases.util.Providers;
 
 import jdk.vm.ci.amd64.AMD64;
@@ -545,7 +549,14 @@
     @Override
     public Variable emitArrayEquals(JavaKind kind, Value array1, Value array2, Value length, int constantLength, boolean directPointers) {
         Variable result = newVariable(LIRKind.value(AMD64Kind.DWORD));
-        append(new AMD64ArrayEqualsOp(this, kind, result, array1, array2, asAllocatable(length), constantLength, directPointers, getMaxVectorSize()));
+        append(new AMD64ArrayEqualsOp(this, kind, kind, result, array1, array2, asAllocatable(length), constantLength, directPointers, getMaxVectorSize()));
+        return result;
+    }
+
+    @Override
+    public Variable emitArrayEquals(JavaKind kind1, JavaKind kind2, Value array1, Value array2, Value length, int constantLength, boolean directPointers) {
+        Variable result = newVariable(LIRKind.value(AMD64Kind.DWORD));
+        append(new AMD64ArrayEqualsOp(this, kind1, kind2, result, array1, array2, asAllocatable(length), constantLength, directPointers, getMaxVectorSize()));
         return result;
     }
 
@@ -635,6 +646,19 @@
     }
 
     @Override
+    protected Optional<Hasher> hasherFor(JavaConstant[] keyConstants, double minDensity) {
+        return Hasher.forKeys(keyConstants, minDensity);
+    }
+
+    @Override
+    protected void emitHashTableSwitch(Hasher hasher, JavaConstant[] keys, LabelRef defaultTarget, LabelRef[] targets, Value value) {
+        Value index = hasher.hash(value, arithmeticLIRGen);
+        Variable scratch = newVariable(LIRKind.value(target().arch.getWordKind()));
+        Variable entryScratch = newVariable(LIRKind.value(target().arch.getWordKind()));
+        append(new HashTableSwitchOp(keys, defaultTarget, targets, value, index, scratch, entryScratch));
+    }
+
+    @Override
     public void emitPause() {
         append(new AMD64PauseOp());
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java	Tue Mar 12 19:17:42 2019 +0100
@@ -83,8 +83,8 @@
     @Option(help = "", type = OptionType.Debug)
     public static final OptionKey<String> EscapeAnalyzeOnly = new OptionKey<>(null);
 
-    @Option(help = "", type = OptionType.Expert)
-    public static final OptionKey<Integer> MaximumEscapeAnalysisArrayLength = new OptionKey<>(32);
+    @Option(help = "The maximum length of an array that will be escape analyzed.", type = OptionType.Expert)
+    public static final OptionKey<Integer> MaximumEscapeAnalysisArrayLength = new OptionKey<>(128);
 
     @Option(help = "", type = OptionType.Debug)
     public static final OptionKey<Boolean> PEAInliningHints = new OptionKey<>(false);
@@ -142,7 +142,7 @@
     public static final OptionKey<Boolean> VerifyPhases = new OptionKey<>(false);
 
     // Debug settings:
-    @Option(help = "", type = OptionType.Debug)
+    @Option(help = "Start tracing compiled GC barriers after N garbage collections (disabled if N <= 0).", type = OptionType.Debug)
     public static final OptionKey<Integer> GCDebugStartCycle = new OptionKey<>(-1);
 
     @Option(help = "Perform platform dependent validation of the Java heap at returns", type = OptionType.Debug)
@@ -206,9 +206,6 @@
     @Option(help = "Generate position independent code", type = OptionType.Expert)
     public static final OptionKey<Boolean> GeneratePIC = new OptionKey<>(false);
 
-    @Option(help = "", type = OptionType.Expert)
-    public static final OptionKey<Boolean> CallArrayCopy = new OptionKey<>(true);
-
     // Runtime settings
     @Option(help = "", type = OptionType.Expert)
     public static final OptionKey<Boolean> SupportJsrBytecodes = new OptionKey<>(true);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/SpeculativeExecutionAttacksMitigations.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/SpeculativeExecutionAttacksMitigations.java	Tue Mar 12 19:17:42 2019 +0100
@@ -37,9 +37,9 @@
 
     public static class Options {
         // @formatter:off
-        @Option(help = "Select a strategy to mitigate speculative execution attacks (e.g., SPECTRE)", type = OptionType.User)
+        @Option(help = "file:doc-files/MitigateSpeculativeExecutionAttacksHelp.txt")
         public static final EnumOptionKey<SpeculativeExecutionAttacksMitigations> MitigateSpeculativeExecutionAttacks = new EnumOptionKey<>(None);
-        @Option(help = "Use index masking after bounds check to mitigate speculative execution attacks", type = OptionType.User)
+        @Option(help = "Use index masking after bounds check to mitigate speculative execution attacks.", type = OptionType.User)
         public static final OptionKey<Boolean> UseIndexMasking = new OptionKey<>(false);
         // @formatter:on
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractBlockBase.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractBlockBase.java	Tue Mar 12 19:17:42 2019 +0100
@@ -24,6 +24,8 @@
 
 package org.graalvm.compiler.core.common.cfg;
 
+import java.util.Comparator;
+
 public abstract class AbstractBlockBase<T extends AbstractBlockBase<T>> {
 
     protected int id;
@@ -171,4 +173,13 @@
     public int hashCode() {
         return id;
     }
+
+    public static class BlockIdComparator implements Comparator<AbstractBlockBase<?>> {
+        @Override
+        public int compare(AbstractBlockBase<?> o1, AbstractBlockBase<?> o2) {
+            return Integer.compare(o1.getId(), o2.getId());
+        }
+    }
+
+    public static final BlockIdComparator BLOCK_ID_COMPARATOR = new BlockIdComparator();
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/CFGVerifier.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/CFGVerifier.java	Tue Mar 12 19:17:42 2019 +0100
@@ -121,7 +121,7 @@
                     }
                 }
 
-                for (T block : loop.getExits()) {
+                for (T block : loop.getLoopExits()) {
                     assert block.getId() >= loop.getHeader().getId();
 
                     Loop<?> blockLoop = block.getLoop();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/Loop.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/Loop.java	Tue Mar 12 19:17:42 2019 +0100
@@ -25,19 +25,28 @@
 
 package org.graalvm.compiler.core.common.cfg;
 
+import static org.graalvm.compiler.core.common.cfg.AbstractBlockBase.BLOCK_ID_COMPARATOR;
+
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 public abstract class Loop<T extends AbstractBlockBase<T>> {
 
     private final Loop<T> parent;
-    private final List<Loop<T>> children;
+    private final ArrayList<Loop<T>> children;
 
     private final int depth;
     private final int index;
     private final T header;
-    private final List<T> blocks;
-    private final List<T> exits;
+    private final ArrayList<T> blocks;
+    private final ArrayList<T> exits;
+    /**
+     * Natural exits, ignoring LoopExitNodes.
+     *
+     * @see #getNaturalExits()
+     */
+    private final ArrayList<T> naturalExits;
 
     protected Loop(Loop<T> parent, int index, T header) {
         this.parent = parent;
@@ -51,6 +60,7 @@
         this.blocks = new ArrayList<>();
         this.children = new ArrayList<>();
         this.exits = new ArrayList<>();
+        this.naturalExits = new ArrayList<>();
     }
 
     public abstract long numBackedges();
@@ -84,12 +94,87 @@
         return blocks;
     }
 
-    public List<T> getExits() {
+    /**
+     * Returns the loop exits.
+     *
+     * This might be a conservative set: before framestate assignment it matches the LoopExitNodes
+     * even if earlier blocks could be considered as exits. After framestate assignments, this is
+     * the same as {@link #getNaturalExits()}.
+     *
+     * <p>
+     * LoopExitNodes are inserted in the control-flow during parsing and are natural exits: they are
+     * the earliest block at which we are guaranteed to have exited the loop. However, after some
+     * transformations of the graph, the natural exit might go up but the LoopExitNodes are not
+     * updated.
+     * </p>
+     *
+     * <p>
+     * For example in:
+     *
+     * <pre>
+     * for (int i = 0; i < N; i++) {
+     *     if (c) {
+     *         // Block 1
+     *         if (dummy) {
+     *             // ...
+     *         } else {
+     *             // ...
+     *         }
+     *         if (b) {
+     *             continue;
+     *         } else {
+     *             // Block 2
+     *             // LoopExitNode
+     *             break;
+     *         }
+     *     }
+     * }
+     * </pre>
+     *
+     * After parsing, the natural exits match the LoopExitNode: Block 2 is a natural exit and has a
+     * LoopExitNode. If the {@code b} condition gets canonicalized to {@code false}, the natural
+     * exit moves to Block 1 while the LoopExitNode remains in Block 2. In such a scenario,
+     * {@code getLoopExits()} will contain block 2 while {@link #getNaturalExits()} will contain
+     * block 1.
+     *
+     *
+     * @see #getNaturalExits()
+     */
+    public List<T> getLoopExits() {
         return exits;
     }
 
-    public void addExit(T t) {
-        exits.add(t);
+    public boolean isLoopExit(T block) {
+        assert isSorted(exits);
+        return Collections.binarySearch(exits, block, BLOCK_ID_COMPARATOR) >= 0;
+    }
+
+    /**
+     * Returns the natural exit points: these are the earliest block that are guaranteed to never
+     * reach a back-edge.
+     *
+     * This can not be used in the context of preserving or using loop-closed form.
+     *
+     * @see #getLoopExits()
+     */
+    public ArrayList<T> getNaturalExits() {
+        return naturalExits;
+    }
+
+    public boolean isNaturalExit(T block) {
+        assert isSorted(naturalExits);
+        return Collections.binarySearch(naturalExits, block, BLOCK_ID_COMPARATOR) >= 0;
+    }
+
+    private static <T extends AbstractBlockBase<T>> boolean isSorted(List<T> list) {
+        int lastId = Integer.MIN_VALUE;
+        for (AbstractBlockBase<?> block : list) {
+            if (block.getId() < lastId) {
+                return false;
+            }
+            lastId = block.getId();
+        }
+        return true;
     }
 
     /**
@@ -115,4 +200,9 @@
     public int hashCode() {
         return index + depth * 31;
     }
+
+    @Override
+    public boolean equals(Object obj) {
+        return super.equals(obj);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/doc-files/MitigateSpeculativeExecutionAttacksHelp.txt	Tue Mar 12 19:17:42 2019 +0100
@@ -0,0 +1,9 @@
+Select a strategy to mitigate speculative execution attacks (e.g., SPECTRE).
+The accepted values are:
+                  None - No mitigations are used in JIT compiled code.
+            AllTargets - All branches are protected against speculative attacks.
+                         This has a significant performance impact.
+          GuardTargets - Only branches that preserve Java memory safety are protected.
+                         This has less performance impact than AllTargets.
+  NonDeoptGuardTargets - GuardTargets except that branches which deoptimize are not
+                         protected since they can not be executed repeatedly.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/AbstractObjectStamp.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/AbstractObjectStamp.java	Tue Mar 12 19:17:42 2019 +0100
@@ -48,6 +48,13 @@
         this.exactType = exactType;
     }
 
+    @Override
+    public void accept(Visitor v) {
+        super.accept(v);
+        v.visitObject(type);
+        v.visitBoolean(exactType);
+    }
+
     protected abstract AbstractObjectStamp copyWith(ResolvedJavaType newType, boolean newExactType, boolean newNonNull, boolean newAlwaysNull);
 
     @Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/AbstractPointerStamp.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/AbstractPointerStamp.java	Tue Mar 12 19:17:42 2019 +0100
@@ -36,6 +36,12 @@
     private final boolean nonNull;
     private final boolean alwaysNull;
 
+    @Override
+    public void accept(Visitor v) {
+        v.visitBoolean(nonNull);
+        v.visitBoolean(alwaysNull);
+    }
+
     protected AbstractPointerStamp(boolean nonNull, boolean alwaysNull) {
         this.nonNull = nonNull;
         this.alwaysNull = alwaysNull;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IllegalStamp.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IllegalStamp.java	Tue Mar 12 19:17:42 2019 +0100
@@ -46,6 +46,10 @@
     }
 
     @Override
+    public void accept(Visitor v) {
+    }
+
+    @Override
     public JavaKind getStackKind() {
         return JavaKind.Illegal;
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ObjectStamp.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ObjectStamp.java	Tue Mar 12 19:17:42 2019 +0100
@@ -31,6 +31,7 @@
 import jdk.vm.ci.meta.JavaConstant;
 import jdk.vm.ci.meta.MemoryAccessProvider;
 import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.meta.UnresolvedJavaType;
 
 public class ObjectStamp extends AbstractObjectStamp {
 
@@ -92,4 +93,48 @@
             return null;
         }
     }
+
+    /**
+     * Convert an ObjectStamp into a representation that can be resolved symbolically into the
+     * original stamp.
+     */
+    @Override
+    public SymbolicJVMCIReference<ObjectStamp> makeSymbolic() {
+        if (type() == null) {
+            return null;
+        }
+        return new SymbolicObjectStamp(this);
+    }
+
+    static class SymbolicObjectStamp implements SymbolicJVMCIReference<ObjectStamp> {
+        UnresolvedJavaType type;
+        private boolean exactType;
+        private boolean nonNull;
+        private boolean alwaysNull;
+
+        SymbolicObjectStamp(ObjectStamp stamp) {
+            if (stamp.type() != null) {
+                type = UnresolvedJavaType.create(stamp.type().getName());
+            }
+            exactType = stamp.isExactType();
+            nonNull = stamp.nonNull();
+            alwaysNull = stamp.alwaysNull();
+        }
+
+        @Override
+        public ObjectStamp resolve(ResolvedJavaType accessingClass) {
+            return new ObjectStamp(type != null ? type.resolve(accessingClass) : null, exactType, nonNull, alwaysNull);
+        }
+
+        @Override
+        public String toString() {
+            return "SymbolicObjectStamp{" +
+                            "declaringType=" + type +
+                            ", exactType=" + exactType +
+                            ", nonNull=" + nonNull +
+                            ", alwaysNull=" + alwaysNull +
+                            '}';
+        }
+    }
+
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/PrimitiveStamp.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/PrimitiveStamp.java	Tue Mar 12 19:17:42 2019 +0100
@@ -39,6 +39,11 @@
         this.bits = bits;
     }
 
+    @Override
+    public void accept(Visitor v) {
+        v.visitInt(bits);
+    }
+
     /**
      * The width in bits of the value described by this stamp.
      */
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/Stamp.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/Stamp.java	Tue Mar 12 19:17:42 2019 +0100
@@ -26,6 +26,7 @@
 
 import org.graalvm.compiler.core.common.LIRKind;
 import org.graalvm.compiler.core.common.spi.LIRKindTool;
+import org.graalvm.compiler.serviceprovider.SpeculationReasonGroup.SpeculationContextObject;
 
 import jdk.vm.ci.meta.Constant;
 import jdk.vm.ci.meta.JavaKind;
@@ -36,7 +37,7 @@
 /**
  * A stamp is the basis for a type system.
  */
-public abstract class Stamp {
+public abstract class Stamp implements SpeculationContextObject {
 
     protected Stamp() {
     }
@@ -185,4 +186,15 @@
         }
         return false;
     }
+
+    /**
+     * Convert a Stamp into a representation that can be resolved symbolically into the original
+     * stamp. If this stamp contains no references to JVMCI types then simply return null.
+     */
+    public SymbolicJVMCIReference<? extends Stamp> makeSymbolic() {
+        return null;
+    }
+
+    @Override
+    public abstract String toString();
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/StampPair.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/StampPair.java	Tue Mar 12 19:17:42 2019 +0100
@@ -24,6 +24,8 @@
 
 package org.graalvm.compiler.core.common.type;
 
+import java.util.Objects;
+
 /**
  * A pair of stamp with one being the stamp that can be trusted and the other one being a guess that
  * needs a dynamic check to be used.
@@ -63,4 +65,22 @@
             return trustedStamp + " (unchecked=" + uncheckedStamp + ")";
         }
     }
+
+    @Override
+    public int hashCode() {
+        return trustedStamp.hashCode() + 11 + (uncheckedStamp != null ? uncheckedStamp.hashCode() : 0);
+
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (obj instanceof StampPair) {
+            StampPair other = (StampPair) obj;
+            return trustedStamp.equals(other.trustedStamp) && Objects.equals(uncheckedStamp, other.uncheckedStamp);
+        }
+        return false;
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/SymbolicJVMCIReference.java	Tue Mar 12 19:17:42 2019 +0100
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 org.graalvm.compiler.core.common.type;
+
+import jdk.vm.ci.meta.ResolvedJavaType;
+
+/**
+ * This interface represents an object which contains a symbolic reference to a JVMCI type or method
+ * that can be converted back into the original object by looking up types relative to an
+ * {@code accessingClass}.
+ */
+public interface SymbolicJVMCIReference<T> {
+    T resolve(ResolvedJavaType accessingClass);
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/VoidStamp.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/VoidStamp.java	Tue Mar 12 19:17:42 2019 +0100
@@ -43,6 +43,10 @@
     }
 
     @Override
+    public void accept(Visitor v) {
+    }
+
+    @Override
     public Stamp unrestricted() {
         return this;
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/UnsignedLong.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/UnsignedLong.java	Tue Mar 12 19:17:42 2019 +0100
@@ -43,6 +43,10 @@
         return Long.compareUnsigned(value, unsignedValue) < 0;
     }
 
+    public boolean isGreaterThan(long unsignedValue) {
+        return Long.compareUnsigned(value, unsignedValue) > 0;
+    }
+
     public boolean isLessOrEqualTo(long unsignedValue) {
         return Long.compareUnsigned(value, unsignedValue) <= 0;
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java	Tue Mar 12 19:17:42 2019 +0100
@@ -157,6 +157,10 @@
                 if (className.equals("org.graalvm.compiler.serviceprovider.GraalServices$Lazy")) {
                     return false;
                 }
+            } else {
+                if (className.equals("jdk.vm.ci.services.JVMCIClassLoaderFactory")) {
+                    return false;
+                }
             }
             return true;
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java	Tue Mar 12 19:17:42 2019 +0100
@@ -33,7 +33,7 @@
 import org.graalvm.compiler.phases.OptimisticOptimizations.Optimization;
 import org.graalvm.compiler.phases.common.CanonicalizerPhase;
 import org.graalvm.compiler.phases.common.ConditionalEliminationPhase;
-import org.graalvm.compiler.phases.common.ConvertDeoptimizeToGuardPhase;
+import org.graalvm.compiler.loop.phases.ConvertDeoptimizeToGuardPhase;
 import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase;
 import org.graalvm.compiler.phases.common.LoweringPhase;
 import org.graalvm.compiler.phases.schedule.SchedulePhase;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CountedLoopTest2.java	Tue Mar 12 19:17:42 2019 +0100
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 org.graalvm.compiler.core.test;
+
+import org.graalvm.compiler.api.directives.GraalDirectives;
+import org.graalvm.compiler.graph.Node;
+import org.graalvm.compiler.graph.iterators.FilteredNodeIterable;
+import org.graalvm.compiler.loop.LoopEx;
+import org.graalvm.compiler.loop.LoopsData;
+import org.graalvm.compiler.nodes.DeoptimizingNode;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class CountedLoopTest2 extends GraalCompilerTest {
+    public static float countedDeoptLoop0(int n) {
+        float v = 0;
+        for (int i = 0; i < n; i++) {
+            v += 2.1f * i;
+            GraalDirectives.controlFlowAnchor();
+        }
+        GraalDirectives.deoptimizeAndInvalidate();
+        return v;
+    }
+
+    @Test
+    public void test0() {
+        test("countedDeoptLoop0");
+    }
+
+    public static float countedDeoptLoop1(int n) {
+        float v = 0;
+        for (int i = 0; i < n; i++) {
+            v += 2.1f * i;
+            GraalDirectives.controlFlowAnchor();
+        }
+        if (v > 0) {
+            if (v / 55 < 3) {
+                v -= 2;
+                GraalDirectives.controlFlowAnchor();
+            } else {
+                v += 6;
+                GraalDirectives.controlFlowAnchor();
+            }
+        } else {
+            v += 1;
+            GraalDirectives.controlFlowAnchor();
+        }
+        GraalDirectives.deoptimizeAndInvalidate();
+        return v;
+    }
+
+    @Test
+    public void test1() {
+        test("countedDeoptLoop1");
+    }
+
+    public static float countedDeoptLoop2(int n, float init) {
+        float v = init;
+        if (v > 0) {
+            if (v / 55 < 3) {
+                for (int i = 0; i < n; i++) {
+                    v += 2.1f * i;
+                    GraalDirectives.controlFlowAnchor();
+                }
+            } else {
+                for (int i = 0; i < n; i++) {
+                    v += 1.1f * i;
+                    GraalDirectives.controlFlowAnchor();
+                }
+            }
+        } else {
+            for (int i = 0; i < n; i++) {
+                v += -0.1f * i;
+                GraalDirectives.controlFlowAnchor();
+            }
+        }
+        GraalDirectives.deoptimizeAndInvalidate();
+        return v;
+    }
+
+    @Test
+    public void test2() {
+        test("countedDeoptLoop2", 3);
+    }
+
+    private void test(String methodName) {
+        test(methodName, 1);
+    }
+
+    private void test(String methodName, int nLoops) {
+        StructuredGraph graph = parseEager(methodName, AllowAssumptions.YES);
+        LoopsData loops = new LoopsData(graph);
+        Assert.assertEquals(nLoops, loops.loops().size());
+        for (LoopEx loop : loops.loops()) {
+            Assert.assertTrue(loop.detectCounted());
+        }
+
+        StructuredGraph finalGraph = getFinalGraph(methodName);
+        loops = new LoopsData(finalGraph);
+        Assert.assertEquals(nLoops, loops.loops().size());
+        FilteredNodeIterable<Node> nonStartDeopts = finalGraph.getNodes().filter(n -> {
+            return n instanceof DeoptimizingNode.DeoptBefore && ((DeoptimizingNode.DeoptBefore) n).stateBefore().bci > 0;
+        });
+        Assert.assertTrue(nonStartDeopts.isNotEmpty());
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DumpPathTest.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DumpPathTest.java	Tue Mar 12 19:17:42 2019 +0100
@@ -31,6 +31,7 @@
 
 import jdk.internal.vm.compiler.collections.EconomicMap;
 import org.graalvm.compiler.debug.DebugOptions;
+import org.graalvm.compiler.debug.DebugOptions.PrintGraphTarget;
 import org.graalvm.compiler.options.OptionKey;
 import org.graalvm.compiler.options.OptionValues;
 import org.junit.Test;
@@ -52,7 +53,7 @@
         String[] extensions = new String[]{".cfg", ".bgv", ".graph-strings"};
         EconomicMap<OptionKey<?>, Object> overrides = OptionValues.newOptionMap();
         overrides.put(DebugOptions.DumpPath, dumpDirectoryPath.toString());
-        overrides.put(DebugOptions.PrintGraphFile, true);
+        overrides.put(DebugOptions.PrintGraph, PrintGraphTarget.File);
         overrides.put(DebugOptions.PrintCanonicalGraphStrings, true);
         overrides.put(DebugOptions.Dump, "*");
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java	Tue Mar 12 19:17:42 2019 +0100
@@ -111,7 +111,7 @@
 import org.graalvm.compiler.phases.Phase;
 import org.graalvm.compiler.phases.PhaseSuite;
 import org.graalvm.compiler.phases.common.CanonicalizerPhase;
-import org.graalvm.compiler.phases.common.ConvertDeoptimizeToGuardPhase;
+import org.graalvm.compiler.loop.phases.ConvertDeoptimizeToGuardPhase;
 import org.graalvm.compiler.phases.common.inlining.InliningPhase;
 import org.graalvm.compiler.phases.common.inlining.info.InlineInfo;
 import org.graalvm.compiler.phases.common.inlining.policy.GreedyInliningPolicy;
@@ -899,11 +899,21 @@
         return actual;
     }
 
+    private static final List<Class<?>> C2_OMIT_STACK_TRACE_IN_FAST_THROW_EXCEPTIONS = Arrays.asList(
+                    ArithmeticException.class,
+                    ArrayIndexOutOfBoundsException.class,
+                    ArrayStoreException.class,
+                    ClassCastException.class,
+                    NullPointerException.class);
+
     protected void assertEquals(Result expect, Result actual) {
         if (expect.exception != null) {
             Assert.assertTrue("expected " + expect.exception, actual.exception != null);
             Assert.assertEquals("Exception class", expect.exception.getClass(), actual.exception.getClass());
-            Assert.assertEquals("Exception message", expect.exception.getMessage(), actual.exception.getMessage());
+            // C2 can optimize out the stack trace and message in some cases
+            if (expect.exception.getMessage() != null || !C2_OMIT_STACK_TRACE_IN_FAST_THROW_EXCEPTIONS.contains(expect.exception.getClass())) {
+                Assert.assertEquals("Exception message", expect.exception.getMessage(), actual.exception.getMessage());
+            }
         } else {
             if (actual.exception != null) {
                 throw new AssertionError("expected " + expect.returnValue + " but got an exception", actual.exception);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphEncoderTest.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphEncoderTest.java	Tue Mar 12 19:17:42 2019 +0100
@@ -30,16 +30,15 @@
 import java.util.List;
 import java.util.Map;
 
-import jdk.vm.ci.meta.ResolvedJavaMethod;
-
-import org.junit.Test;
-
 import org.graalvm.compiler.nodes.EncodedGraph;
 import org.graalvm.compiler.nodes.GraphEncoder;
 import org.graalvm.compiler.nodes.StructuredGraph;
 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
 import org.graalvm.compiler.phases.common.CanonicalizerPhase;
 import org.graalvm.compiler.phases.tiers.PhaseContext;
+import org.junit.Test;
+
+import jdk.vm.ci.meta.ResolvedJavaMethod;
 
 public class GraphEncoderTest extends GraalCompilerTest {
 
@@ -80,7 +79,7 @@
 
         for (StructuredGraph originalGraph : originalGraphs) {
             EncodedGraph encodedGraph = new EncodedGraph(encoder.getEncoding(), startOffsets.get(originalGraph), encoder.getObjects(), encoder.getNodeClasses(), originalGraph);
-            GraphEncoder.verifyEncoding(originalGraph, encodedGraph, getTarget().arch);
+            encoder.verifyEncoding(originalGraph, encodedGraph);
         }
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardPrioritiesTest.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardPrioritiesTest.java	Tue Mar 12 19:17:42 2019 +0100
@@ -35,6 +35,7 @@
 import org.graalvm.compiler.api.directives.GraalDirectives;
 import org.graalvm.compiler.core.common.GraalOptions;
 import org.graalvm.compiler.graph.iterators.NodeIterable;
+import org.graalvm.compiler.loop.phases.ConvertDeoptimizeToGuardPhase;
 import org.graalvm.compiler.nodes.GuardNode;
 import org.graalvm.compiler.nodes.ParameterNode;
 import org.graalvm.compiler.nodes.StructuredGraph;
@@ -42,7 +43,6 @@
 import org.graalvm.compiler.nodes.calc.IsNullNode;
 import org.graalvm.compiler.nodes.spi.LoweringTool;
 import org.graalvm.compiler.phases.common.CanonicalizerPhase;
-import org.graalvm.compiler.phases.common.ConvertDeoptimizeToGuardPhase;
 import org.graalvm.compiler.phases.common.FloatingReadPhase;
 import org.graalvm.compiler.phases.common.LoweringPhase;
 import org.graalvm.compiler.phases.schedule.SchedulePhase;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IntegerDivRemConstantTest.java	Tue Mar 12 19:17:42 2019 +0100
@@ -0,0 +1,293 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, Arm Limited and affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 org.graalvm.compiler.core.test;
+
+import org.junit.Test;
+
+public class IntegerDivRemConstantTest extends GraalCompilerTest {
+    public static int intDivPositiveConstant(int val) {
+        return val / 5;
+    }
+
+    @Test
+    public void testIntDivPositiveConstant() {
+        test("intDivPositiveConstant", -10);
+        test("intDivPositiveConstant", 0);
+        test("intDivPositiveConstant", 4256);
+        test("intDivPositiveConstant", Integer.MAX_VALUE);
+        test("intDivPositiveConstant", Integer.MIN_VALUE);
+    }
+
+    public static int intDivIntegerMax(int val) {
+        return val / Integer.MAX_VALUE;
+    }
+
+    @Test
+    public void testIntDivIntegerMax() {
+        test("intDivIntegerMax", -10);
+        test("intDivIntegerMax", 0);
+        test("intDivIntegerMax", 4256);
+        test("intDivIntegerMax", Integer.MAX_VALUE);
+        test("intDivIntegerMax", Integer.MIN_VALUE);
+    }
+
+    public static int intDivNegativeConstant(int val) {
+        return val / -1234;
+    }
+
+    @Test
+    public void testIntDivNegativeConstant() {
+        test("intDivNegativeConstant", -123);
+        test("intDivNegativeConstant", 0);
+        test("intDivNegativeConstant", 123);
+        test("intDivNegativeConstant", Integer.MAX_VALUE);
+        test("intDivNegativeConstant", Integer.MIN_VALUE);
+    }
+
+    public static int intDivIntegerMinOdd(int val) {
+        return val / (Integer.MIN_VALUE + 1);
+    }
+
+    @Test
+    public void testIntDivIntegerMinOdd() {
+        test("intDivIntegerMinOdd", -123);
+        test("intDivIntegerMinOdd", 0);
+        test("intDivIntegerMinOdd", 123);
+        test("intDivIntegerMinOdd", Integer.MAX_VALUE);
+        test("intDivIntegerMinOdd", Integer.MIN_VALUE);
+    }
+
+    public static long longDivPositiveConstant(long val) {
+        return val / 35170432;
+    }
+
+    @Test
+    public void testLongDivPositiveConstant() {
+        test("longDivPositiveConstant", -1234L);
+        test("longDivPositiveConstant", 0L);
+        test("longDivPositiveConstant", 214423L);
+        test("longDivPositiveConstant", Long.MAX_VALUE);
+        test("longDivPositiveConstant", Long.MIN_VALUE);
+    }
+
+    public static long longDivLongMax(long val) {
+        return val / Long.MAX_VALUE;
+    }
+
+    @Test
+    public void testLongDivLongMax() {
+        test("longDivLongMax", -1234L);
+        test("longDivLongMax", 0L);
+        test("longDivLongMax", 214423L);
+        test("longDivLongMax", Long.MAX_VALUE);
+        test("longDivLongMax", Long.MIN_VALUE);
+    }
+
+    public static long longDivNegativeConstant(long val) {
+        return val / -413;
+    }
+
+    @Test
+    public void testLongDivNegativeConstant() {
+        test("longDivNegativeConstant", -43L);
+        test("longDivNegativeConstant", 0L);
+        test("longDivNegativeConstant", 147065L);
+        test("longDivNegativeConstant", Long.MAX_VALUE);
+        test("longDivNegativeConstant", Long.MIN_VALUE);
+    }
+
+    public static long longDivLongMinOdd(long val) {
+        return val / (Long.MIN_VALUE + 1);
+    }
+
+    @Test
+    public void testLongDivLongMinOdd() {
+        test("longDivLongMinOdd", -1234L);
+        test("longDivLongMinOdd", 0L);
+        test("longDivLongMinOdd", 214423L);
+        test("longDivLongMinOdd", Long.MAX_VALUE);
+        test("longDivLongMinOdd", Long.MIN_VALUE);
+    }
+
+    public static int intRemPositiveConstant(int val) {
+        return val % 139968;
+    }
+
+    @Test
+    public void testIntRemPositiveConstant() {
+        test("intRemPositiveConstant", -10);
+        test("intRemPositiveConstant", 0);
+        test("intRemPositiveConstant", 4256);
+        test("intRemPositiveConstant", Integer.MAX_VALUE);
+        test("intRemPositiveConstant", Integer.MIN_VALUE);
+    }
+
+    public static int intRemNegativeConstant(int val) {
+        return val % -139968;
+    }
+
+    @Test
+    public void testIntRemNegativeConstant() {
+        test("intRemNegativeConstant", -10);
+        test("intRemNegativeConstant", 0);
+        test("intRemNegativeConstant", 4256);
+        test("intRemNegativeConstant", Integer.MAX_VALUE);
+        test("intRemNegativeConstant", Integer.MIN_VALUE);
+    }
+
+    @SuppressWarnings("divzero")
+    public static int intRemZero(int val) {
+        return val % 0;
+    }
+
+    @Test
+    public void testIntRemZero() {
+        test("intRemZero", -10);
+        test("intRemZero", 0);
+        test("intRemZero", 4256);
+        test("intRemZero", Integer.MAX_VALUE);
+        test("intRemZero", Integer.MIN_VALUE);
+    }
+
+    public static int intRemMax(int val) {
+        return val % Integer.MAX_VALUE;
+    }
+
+    @Test
+    public void testIntRemMax() {
+        test("intRemMax", -10);
+        test("intRemMax", 0);
+        test("intRemMax", 4256);
+        test("intRemMax", Integer.MAX_VALUE);
+        test("intRemMax", Integer.MIN_VALUE);
+    }
+
+    public static int intRemMin(int val) {
+        return val % Integer.MIN_VALUE;
+    }
+
+    @Test
+    public void testIntRemMin() {
+        test("intRemMin", -10);
+        test("intRemMin", 0);
+        test("intRemMin", 4256);
+        test("intRemMin", Integer.MAX_VALUE);
+        test("intRemMin", Integer.MIN_VALUE);
+    }
+
+    public static long longRemPositiveConstant(long val) {
+        return val % 35170432;
+    }
+
+    public static int intRemPowerOf2(int val) {
+        return val % 4;
+    }
+
+    @Test
+    public void testIntRemPowerOf2() {
+        test("intRemPowerOf2", -10);
+        test("intRemPowerOf2", 0);
+        test("intRemPowerOf2", 4256);
+        test("intRemPowerOf2", Integer.MAX_VALUE);
+        test("intRemPowerOf2", Integer.MIN_VALUE);
+    }
+
+    @Test
+    public void testLongRemPositiveConstant() {
+        test("longRemPositiveConstant", -1234L);
+        test("longRemPositiveConstant", 0L);
+        test("longRemPositiveConstant", 214423L);
+        test("longRemPositiveConstant", Long.MAX_VALUE);
+        test("longRemPositiveConstant", Long.MIN_VALUE);
+    }
+
+    public static long longRemNegativeConstant(long val) {
+        return val % -413;
+    }
+
+    @Test
+    public void testLongRemNegativeConstant() {
+        test("longRemNegativeConstant", -43L);
+        test("longRemNegativeConstant", 0L);
+        test("longRemNegativeConstant", 147065L);
+        test("longRemNegativeConstant", Long.MAX_VALUE);
+        test("longRemNegativeConstant", Long.MIN_VALUE);
+    }
+
+    @SuppressWarnings("divzero")
+    public static long longRemZero(long val) {
+        return val % 0;
+    }
+
+    @Test
+    public void testLongRemZero() {
+        test("longRemZero", -43L);
+        test("longRemZero", 0L);
+        test("longRemZero", 147065L);
+        test("longRemZero", Long.MAX_VALUE);
+        test("longRemZero", Long.MIN_VALUE);
+    }
+
+    public static long longRemMax(long val) {
+        return val % Long.MAX_VALUE;
+    }
+
+    @Test
+    public void testLongRemMax() {
+        test("longRemMax", -43L);
+        test("longRemMax", 0L);
+        test("longRemMax", 147065L);
+        test("longRemMax", Long.MAX_VALUE);
+        test("longRemMax", Long.MIN_VALUE);
+    }
+
+    public static long longRemMin(long val) {
+        return val % Long.MIN_VALUE;
+    }
+
+    @Test
+    public void testLongRemMin() {
+        test("longRemMin", -43L);
+        test("longRemMin", 0L);
+        test("longRemMin", 147065L);
+        test("longRemMin", Long.MAX_VALUE);
+        test("longRemMin", Long.MIN_VALUE);
+    }
+
+    public static long longRemPowerOf2(long val) {
+        return val % 4L;
+    }
+
+    @Test
+    public void testLongRemPowerOf2() {
+        test("longRemPowerOf2", -43L);
+        test("longRemPowerOf2", 0L);
+        test("longRemPowerOf2", 147065L);
+        test("longRemPowerOf2", Long.MAX_VALUE);
+        test("longRemPowerOf2", Long.MIN_VALUE);
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryScheduleTest.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryScheduleTest.java	Tue Mar 12 19:17:42 2019 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NestedLoopTest.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NestedLoopTest.java	Tue Mar 12 19:17:42 2019 +0100
@@ -161,9 +161,9 @@
         Assert.assertTrue(containsDirect(innerMostLoop, d, cfg));
         Assert.assertTrue(contains(rootLoop, d, cfg));
         Assert.assertTrue(contains(nestedLoop, d, cfg));
-        Assert.assertEquals(rootExits, rootLoop.getExits().size());
-        Assert.assertEquals(nestedExits, nestedLoop.getExits().size());
-        Assert.assertEquals(innerExits, innerMostLoop.getExits().size());
+        Assert.assertEquals(rootExits, rootLoop.getLoopExits().size());
+        Assert.assertEquals(nestedExits, nestedLoop.getLoopExits().size());
+        Assert.assertEquals(innerExits, innerMostLoop.getLoopExits().size());
         debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph");
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SwitchCanonicalizerTest.java	Tue Mar 12 19:17:42 2019 +0100
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 org.graalvm.compiler.core.test;
+
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.extended.IntegerSwitchNode;
+import org.graalvm.compiler.phases.common.CanonicalizerPhase;
+import org.junit.Test;
+
+public class SwitchCanonicalizerTest extends GraalCompilerTest {
+
+    public int divByPowerOf2(int n) {
+        switch (n / 8) {
+            case Integer.MAX_VALUE / 8 + 1:
+                return hashCode();
+            default:
+                return 1;
+        }
+    }
+
+    @Test
+    public void testDivByPowerOf2() {
+        shouldFoldSwitch("divByPowerOf2");
+    }
+
+    public int divByNonPowerOf2(int n) {
+        switch (n / 7) {
+            case Integer.MAX_VALUE / 7 + 1:
+                return hashCode();
+            default:
+                return 1;
+        }
+    }
+
+    @Test
+    public void testDivByNonPowerOf2() {
+        shouldFoldSwitch("divByNonPowerOf2");
+    }
+
+    public int remByPowerOf2(int n) {
+        switch (n % 8) {
+            case 9:
+                return hashCode();
+            default:
+                return 1;
+        }
+    }
+
+    @Test
+    public void testRemByPowerOf2() {
+        shouldFoldSwitch("remByPowerOf2");
+    }
+
+    public int remByPowerOf2PositiveX(int n) {
+        int n0 = n > 0 ? 8 : 9;
+        switch (n0 % 8) {
+            case 9:
+                return hashCode();
+            default:
+                return 1;
+        }
+    }
+
+    @Test
+    public void testRemByPowerOf2PositiveX() {
+        shouldFoldSwitch("remByPowerOf2PositiveX");
+    }
+
+    public int remByPowerOf2NegativeX(int n) {
+        int n0 = n > 0 ? -8 : -9;
+        switch (n0 % 8) {
+            case 9:
+                return hashCode();
+            default:
+                return 1;
+        }
+    }
+
+    @Test
+    public void testRemByPowerOf2NegativeX() {
+        shouldFoldSwitch("remByPowerOf2NegativeX");
+    }
+
+    public int remByNonPowerOf2(int n) {
+        switch (n % 7) {
+            case 9:
+                return hashCode();
+            default:
+                return 1;
+        }
+    }
+
+    @Test
+    public void testRemByNonPowerOf2() {
+        shouldFoldSwitch("remByNonPowerOf2");
+    }
+
+    private void shouldFoldSwitch(String methodName) {
+        StructuredGraph graph = parseForCompile(getResolvedJavaMethod(methodName));
+        new CanonicalizerPhase().apply(graph, getDefaultHighTierContext());
+        assertFalse(graph.hasNode(IntegerSwitchNode.TYPE));
+    }
+
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyCallerSensitiveMethods.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyCallerSensitiveMethods.java	Tue Mar 12 19:17:42 2019 +0100
@@ -24,7 +24,7 @@
 
 package org.graalvm.compiler.core.test;
 
-import static org.graalvm.compiler.serviceprovider.GraalServices.Java8OrEarlier;
+import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.Java8OrEarlier;
 
 import java.lang.annotation.Annotation;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyDebugUsage.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyDebugUsage.java	Tue Mar 12 19:17:42 2019 +0100
@@ -150,7 +150,8 @@
                     "org.graalvm.compiler.truffle.compiler.TruffleCompilerImpl.compilePEGraph",
                     "org.graalvm.compiler.core.test.VerifyDebugUsageTest$ValidDumpUsagePhase.run",
                     "org.graalvm.compiler.core.test.VerifyDebugUsageTest$InvalidConcatDumpUsagePhase.run",
-                    "org.graalvm.compiler.core.test.VerifyDebugUsageTest$InvalidDumpUsagePhase.run"));
+                    "org.graalvm.compiler.core.test.VerifyDebugUsageTest$InvalidDumpUsagePhase.run",
+                    "org.graalvm.compiler.hotspot.SymbolicSnippetEncoder.verifySnippetEncodeDecode"));
 
     /**
      * The set of methods allowed to call a {@code Debug.dump(...)} method with the {@code level}
@@ -165,7 +166,8 @@
                     "org.graalvm.compiler.core.GraalCompiler.emitFrontEnd",
                     "org.graalvm.compiler.phases.BasePhase.dumpAfter",
                     "org.graalvm.compiler.replacements.ReplacementsImpl$GraphMaker.makeGraph",
-                    "org.graalvm.compiler.replacements.SnippetTemplate.instantiate"));
+                    "org.graalvm.compiler.replacements.SnippetTemplate.instantiate",
+                    "org.graalvm.compiler.hotspot.SymbolicSnippetEncoder.verifySnippetEncodeDecode"));
 
     private void verifyParameters(StructuredGraph callerGraph, MethodCallTargetNode debugCallTarget, List<? extends ValueNode> args, ResolvedJavaType stringType, int startArgIdx,
                     int varArgsIndex) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/BackendTest.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/BackendTest.java	Tue Mar 12 19:17:42 2019 +0100
@@ -25,6 +25,7 @@
 package org.graalvm.compiler.core.test.backend;
 
 import org.graalvm.compiler.core.GraalCompiler;
+import org.graalvm.compiler.core.gen.LIRCompilerBackend;
 import org.graalvm.compiler.core.test.GraalCompilerTest;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.lir.gen.LIRGenerationResult;
@@ -52,7 +53,7 @@
             throw debug.handle(e);
         }
 
-        LIRGenerationResult lirGen = GraalCompiler.emitLIR(getBackend(), graph, null, null, createLIRSuites(graph.getOptions()));
+        LIRGenerationResult lirGen = LIRCompilerBackend.emitLIR(getBackend(), graph, null, null, createLIRSuites(graph.getOptions()));
         return lirGen;
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/RethrowDeoptMaterializeTest.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/RethrowDeoptMaterializeTest.java	Tue Mar 12 19:17:42 2019 +0100
@@ -46,7 +46,7 @@
         @SuppressWarnings("sync-override")
         @Override
         public final Throwable fillInStackTrace() {
-            return null;
+            return this;
         }
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java	Tue Mar 12 19:17:42 2019 +0100
@@ -293,7 +293,7 @@
         @SuppressWarnings("sync-override")
         @Override
         public final Throwable fillInStackTrace() {
-            return null;
+            return this;
         }
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java	Tue Mar 12 19:17:42 2019 +0100
@@ -24,42 +24,18 @@
 
 package org.graalvm.compiler.core;
 
-import java.util.Collection;
-import java.util.List;
-
-import jdk.internal.vm.compiler.collections.EconomicSet;
 import org.graalvm.compiler.code.CompilationResult;
-import org.graalvm.compiler.core.LIRGenerationPhase.LIRGenerationContext;
-import org.graalvm.compiler.core.common.GraalOptions;
 import org.graalvm.compiler.core.common.PermanentBailoutException;
 import org.graalvm.compiler.core.common.RetryableBailoutException;
-import org.graalvm.compiler.core.common.alloc.ComputeBlockOrder;
-import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig;
-import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
 import org.graalvm.compiler.core.common.util.CompilationAlarm;
 import org.graalvm.compiler.core.target.Backend;
-import org.graalvm.compiler.debug.CounterKey;
 import org.graalvm.compiler.debug.DebugCloseable;
 import org.graalvm.compiler.debug.DebugContext;
-import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.debug.MethodFilter;
 import org.graalvm.compiler.debug.TimerKey;
-import org.graalvm.compiler.lir.LIR;
-import org.graalvm.compiler.lir.alloc.OutOfRegistersException;
-import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
 import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory;
-import org.graalvm.compiler.lir.framemap.FrameMap;
-import org.graalvm.compiler.lir.framemap.FrameMapBuilder;
-import org.graalvm.compiler.lir.gen.LIRGenerationResult;
-import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
-import org.graalvm.compiler.lir.phases.AllocationPhase.AllocationContext;
 import org.graalvm.compiler.lir.phases.LIRSuites;
-import org.graalvm.compiler.lir.phases.PostAllocationOptimizationPhase.PostAllocationOptimizationContext;
-import org.graalvm.compiler.lir.phases.PreAllocationOptimizationPhase.PreAllocationOptimizationContext;
 import org.graalvm.compiler.nodes.StructuredGraph;
-import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult;
-import org.graalvm.compiler.nodes.cfg.Block;
-import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
 import org.graalvm.compiler.phases.OptimisticOptimizations;
 import org.graalvm.compiler.phases.PhaseSuite;
 import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase;
@@ -70,17 +46,8 @@
 import org.graalvm.compiler.phases.tiers.TargetProvider;
 import org.graalvm.compiler.phases.util.Providers;
 
-import jdk.vm.ci.code.RegisterConfig;
-import jdk.vm.ci.code.TargetDescription;
-import jdk.vm.ci.code.site.ConstantReference;
-import jdk.vm.ci.code.site.DataPatch;
-import jdk.vm.ci.meta.Assumptions;
-import jdk.vm.ci.meta.JavaConstant;
-import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.ProfilingInfo;
-import jdk.vm.ci.meta.ResolvedJavaField;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
-import jdk.vm.ci.meta.VMConstant;
 
 /**
  * Static methods for orchestrating the compilation of a {@linkplain StructuredGraph graph}.
@@ -89,9 +56,6 @@
 
     private static final TimerKey CompilerTimer = DebugContext.timer("GraalCompiler").doc("Time spent in compilation (excludes code installation).");
     private static final TimerKey FrontEnd = DebugContext.timer("FrontEnd").doc("Time spent processing HIR.");
-    private static final TimerKey EmitLIR = DebugContext.timer("EmitLIR").doc("Time spent generating LIR from HIR.");
-    private static final TimerKey EmitCode = DebugContext.timer("EmitCode").doc("Time spent generating machine code from LIR.");
-    private static final TimerKey BackEnd = DebugContext.timer("BackEnd").doc("Time spent in EmitLIR and EmitCode.");
 
     /**
      * Encapsulates all the inputs to a {@linkplain GraalCompiler#compile(Request) compilation}.
@@ -178,7 +142,7 @@
             assert !r.graph.isFrozen();
             try (DebugContext.Scope s0 = debug.scope("GraalCompiler", r.graph, r.providers.getCodeCache()); DebugCloseable a = CompilerTimer.start(debug)) {
                 emitFrontEnd(r.providers, r.backend, r.graph, r.graphBuilderSuite, r.optimisticOpts, r.profilingInfo, r.suites);
-                emitBackEnd(r.graph, null, r.installedCodeOwner, r.backend, r.compilationResult, r.factory, null, r.lirSuites);
+                r.backend.emitBackEnd(r.graph, null, r.installedCodeOwner, r.compilationResult, r.factory, null, r.lirSuites);
                 if (r.verifySourcePositions) {
                     assert r.graph.verifySourcePositions(true);
                 }
@@ -275,85 +239,6 @@
         }
     }
 
-    @SuppressWarnings("try")
-    public static <T extends CompilationResult> void emitBackEnd(StructuredGraph graph, Object stub, ResolvedJavaMethod installedCodeOwner, Backend backend, T compilationResult,
-                    CompilationResultBuilderFactory factory, RegisterConfig registerConfig, LIRSuites lirSuites) {
-        DebugContext debug = graph.getDebug();
-        try (DebugContext.Scope s = debug.scope("BackEnd", graph.getLastSchedule()); DebugCloseable a = BackEnd.start(debug)) {
-            LIRGenerationResult lirGen = null;
-            lirGen = emitLIR(backend, graph, stub, registerConfig, lirSuites);
-            try (DebugContext.Scope s2 = debug.scope("CodeGen", lirGen, lirGen.getLIR())) {
-                int bytecodeSize = graph.method() == null ? 0 : graph.getBytecodeSize();
-                compilationResult.setHasUnsafeAccess(graph.hasUnsafeAccess());
-                emitCode(backend, graph.getAssumptions(), graph.method(), graph.getMethods(), graph.getFields(), bytecodeSize, lirGen, compilationResult, installedCodeOwner, factory);
-            } catch (Throwable e) {
-                throw debug.handle(e);
-            }
-        } catch (Throwable e) {
-            throw debug.handle(e);
-        } finally {
-            graph.checkCancellation();
-        }
-    }
-
-    @SuppressWarnings("try")
-    public static LIRGenerationResult emitLIR(Backend backend, StructuredGraph graph, Object stub, RegisterConfig registerConfig, LIRSuites lirSuites) {
-        String registerPressure = GraalOptions.RegisterPressure.getValue(graph.getOptions());
-        String[] allocationRestrictedTo = registerPressure == null ? null : registerPressure.split(",");
-        try {
-            return emitLIR0(backend, graph, stub, registerConfig, lirSuites, allocationRestrictedTo);
-        } catch (OutOfRegistersException e) {
-            if (allocationRestrictedTo != null) {
-                allocationRestrictedTo = null;
-                return emitLIR0(backend, graph, stub, registerConfig, lirSuites, allocationRestrictedTo);
-            }
-            /* If the re-execution fails we convert the exception into a "hard" failure */
-            throw new GraalError(e);
-        } finally {
-            graph.checkCancellation();
-        }
-    }
-
-    @SuppressWarnings("try")
-    private static LIRGenerationResult emitLIR0(Backend backend, StructuredGraph graph, Object stub, RegisterConfig registerConfig, LIRSuites lirSuites,
-                    String[] allocationRestrictedTo) {
-        DebugContext debug = graph.getDebug();
-        try (DebugContext.Scope ds = debug.scope("EmitLIR"); DebugCloseable a = EmitLIR.start(debug)) {
-            assert !graph.hasValueProxies();
-            ScheduleResult schedule = graph.getLastSchedule();
-            Block[] blocks = schedule.getCFG().getBlocks();
-            Block startBlock = schedule.getCFG().getStartBlock();
-            assert startBlock != null;
-            assert startBlock.getPredecessorCount() == 0;
-
-            AbstractBlockBase<?>[] codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blocks.length, startBlock);
-            AbstractBlockBase<?>[] linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blocks.length, startBlock);
-            LIR lir = new LIR(schedule.getCFG(), linearScanOrder, codeEmittingOrder, graph.getOptions(), graph.getDebug());
-
-            FrameMapBuilder frameMapBuilder = backend.newFrameMapBuilder(registerConfig);
-            LIRGenerationResult lirGenRes = backend.newLIRGenerationResult(graph.compilationId(), lir, frameMapBuilder, graph, stub);
-            LIRGeneratorTool lirGen = backend.newLIRGenerator(lirGenRes);
-            NodeLIRBuilderTool nodeLirGen = backend.newNodeLIRBuilder(graph, lirGen);
-
-            // LIR generation
-            LIRGenerationContext context = new LIRGenerationContext(lirGen, nodeLirGen, graph, schedule);
-            new LIRGenerationPhase().apply(backend.getTarget(), lirGenRes, context);
-
-            try (DebugContext.Scope s = debug.scope("LIRStages", nodeLirGen, lirGenRes, lir)) {
-                // Dump LIR along with HIR (the LIR is looked up from context)
-                debug.dump(DebugContext.BASIC_LEVEL, graph.getLastSchedule(), "After LIR generation");
-                LIRGenerationResult result = emitLowLevel(backend.getTarget(), lirGenRes, lirGen, lirSuites, backend.newRegisterAllocationConfig(registerConfig, allocationRestrictedTo));
-                return result;
-            } catch (Throwable e) {
-                throw debug.handle(e);
-            }
-        } catch (Throwable e) {
-            throw debug.handle(e);
-        } finally {
-            graph.checkCancellation();
-        }
-    }
-
     protected static <T extends CompilationResult> String getCompilationUnitName(StructuredGraph graph, T compilationResult) {
         if (compilationResult != null && compilationResult.getName() != null) {
             return compilationResult.getName();
@@ -364,70 +249,4 @@
         }
         return method.format("%H.%n(%p)");
     }
-
-    public static LIRGenerationResult emitLowLevel(TargetDescription target, LIRGenerationResult lirGenRes, LIRGeneratorTool lirGen, LIRSuites lirSuites,
-                    RegisterAllocationConfig registerAllocationConfig) {
-        DebugContext debug = lirGenRes.getLIR().getDebug();
-        PreAllocationOptimizationContext preAllocOptContext = new PreAllocationOptimizationContext(lirGen);
-        lirSuites.getPreAllocationOptimizationStage().apply(target, lirGenRes, preAllocOptContext);
-        debug.dump(DebugContext.BASIC_LEVEL, lirGenRes.getLIR(), "After PreAllocationOptimizationStage");
-
-        AllocationContext allocContext = new AllocationContext(lirGen.getSpillMoveFactory(), registerAllocationConfig);
-        lirSuites.getAllocationStage().apply(target, lirGenRes, allocContext);
-        debug.dump(DebugContext.BASIC_LEVEL, lirGenRes.getLIR(), "After AllocationStage");
-
-        PostAllocationOptimizationContext postAllocOptContext = new PostAllocationOptimizationContext(lirGen);
-        lirSuites.getPostAllocationOptimizationStage().apply(target, lirGenRes, postAllocOptContext);
-        debug.dump(DebugContext.BASIC_LEVEL, lirGenRes.getLIR(), "After PostAllocationOptimizationStage");
-
-        return lirGenRes;
-    }
-
-    @SuppressWarnings("try")
-    public static void emitCode(Backend backend, Assumptions assumptions, ResolvedJavaMethod rootMethod, Collection<ResolvedJavaMethod> inlinedMethods, EconomicSet<ResolvedJavaField> accessedFields,
-                    int bytecodeSize, LIRGenerationResult lirGenRes,
-                    CompilationResult compilationResult, ResolvedJavaMethod installedCodeOwner, CompilationResultBuilderFactory factory) {
-        DebugContext debug = lirGenRes.getLIR().getDebug();
-        try (DebugCloseable a = EmitCode.start(debug)) {
-            FrameMap frameMap = lirGenRes.getFrameMap();
-            CompilationResultBuilder crb = backend.newCompilationResultBuilder(lirGenRes, frameMap, compilationResult, factory);
-            backend.emitCode(crb, lirGenRes.getLIR(), installedCodeOwner);
-            if (assumptions != null && !assumptions.isEmpty()) {
-                compilationResult.setAssumptions(assumptions.toArray());
-            }
-            if (rootMethod != null) {
-                compilationResult.setMethods(rootMethod, inlinedMethods);
-                compilationResult.setFields(accessedFields);
-                compilationResult.setBytecodeSize(bytecodeSize);
-            }
-            crb.finish();
-            if (debug.isCountEnabled()) {
-                List<DataPatch> ldp = compilationResult.getDataPatches();
-                JavaKind[] kindValues = JavaKind.values();
-                CounterKey[] dms = new CounterKey[kindValues.length];
-                for (int i = 0; i < dms.length; i++) {
-                    dms[i] = DebugContext.counter("DataPatches-%s", kindValues[i]);
-                }
-
-                for (DataPatch dp : ldp) {
-                    JavaKind kind = JavaKind.Illegal;
-                    if (dp.reference instanceof ConstantReference) {
-                        VMConstant constant = ((ConstantReference) dp.reference).getConstant();
-                        if (constant instanceof JavaConstant) {
-                            kind = ((JavaConstant) constant).getJavaKind();
-                        }
-                    }
-                    dms[kind.ordinal()].add(debug, 1);
-                }
-
-                DebugContext.counter("CompilationResults").increment(debug);
-                DebugContext.counter("CodeBytesEmitted").add(debug, compilationResult.getTargetCodeSize());
-                DebugContext.counter("InfopointsEmitted").add(debug, compilationResult.getInfopoints().size());
-                DebugContext.counter("DataPatches").add(debug, ldp.size());
-                DebugContext.counter("ExceptionHandlersEmitted").add(debug, compilationResult.getExceptionHandlers().size());
-            }
-
-            debug.dump(DebugContext.BASIC_LEVEL, compilationResult, "After code generation");
-        }
-    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/LIRCompilerBackend.java	Tue Mar 12 19:17:42 2019 +0100
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 org.graalvm.compiler.core.gen;
+
+import java.util.Collection;
+import java.util.List;
+
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import org.graalvm.compiler.code.CompilationResult;
+import org.graalvm.compiler.core.LIRGenerationPhase;
+import org.graalvm.compiler.core.LIRGenerationPhase.LIRGenerationContext;
+import org.graalvm.compiler.core.common.GraalOptions;
+import org.graalvm.compiler.core.common.alloc.ComputeBlockOrder;
+import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig;
+import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
+import org.graalvm.compiler.core.target.Backend;
+import org.graalvm.compiler.debug.CounterKey;
+import org.graalvm.compiler.debug.DebugCloseable;
+import org.graalvm.compiler.debug.DebugContext;
+import org.graalvm.compiler.debug.GraalError;
+import org.graalvm.compiler.debug.TimerKey;
+import org.graalvm.compiler.lir.LIR;
+import org.graalvm.compiler.lir.alloc.OutOfRegistersException;
+import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
+import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory;
+import org.graalvm.compiler.lir.framemap.FrameMap;
+import org.graalvm.compiler.lir.gen.LIRGenerationResult;
+import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
+import org.graalvm.compiler.lir.phases.AllocationPhase.AllocationContext;
+import org.graalvm.compiler.lir.phases.LIRSuites;
+import org.graalvm.compiler.lir.phases.PostAllocationOptimizationPhase.PostAllocationOptimizationContext;
+import org.graalvm.compiler.lir.phases.PreAllocationOptimizationPhase.PreAllocationOptimizationContext;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult;
+import org.graalvm.compiler.nodes.cfg.Block;
+import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
+
+import jdk.vm.ci.code.RegisterConfig;
+import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.code.site.ConstantReference;
+import jdk.vm.ci.code.site.DataPatch;
+import jdk.vm.ci.meta.Assumptions;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.ResolvedJavaField;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.SpeculationLog;
+import jdk.vm.ci.meta.VMConstant;
+
+public class LIRCompilerBackend {
+    private static final TimerKey EmitLIR = DebugContext.timer("EmitLIR").doc("Time spent generating LIR from HIR.");
+    private static final TimerKey EmitCode = DebugContext.timer("EmitCode").doc("Time spent generating machine code from LIR.");
+    private static final TimerKey BackEnd = DebugContext.timer("BackEnd").doc("Time spent in EmitLIR and EmitCode.");
+
+    @SuppressWarnings("try")
+    public static <T extends CompilationResult> void emitBackEnd(StructuredGraph graph, Object stub, ResolvedJavaMethod installedCodeOwner, Backend backend, T compilationResult,
+                    CompilationResultBuilderFactory factory, RegisterConfig registerConfig, LIRSuites lirSuites) {
+        DebugContext debug = graph.getDebug();
+        try (DebugContext.Scope s = debug.scope("BackEnd", graph.getLastSchedule()); DebugCloseable a = BackEnd.start(debug)) {
+            LIRGenerationResult lirGen = null;
+            lirGen = emitLIR(backend, graph, stub, registerConfig, lirSuites);
+            try (DebugContext.Scope s2 = debug.scope("CodeGen", lirGen, lirGen.getLIR())) {
+                int bytecodeSize = graph.method() == null ? 0 : graph.getBytecodeSize();
+                compilationResult.setHasUnsafeAccess(graph.hasUnsafeAccess());
+                emitCode(backend,
+                                graph.getAssumptions(),
+                                graph.method(),
+                                graph.getMethods(),
+                                graph.getFields(),
+                                graph.getSpeculationLog(),
+                                bytecodeSize,
+                                lirGen,
+                                compilationResult,
+                                installedCodeOwner,
+                                factory);
+            } catch (Throwable e) {
+                throw debug.handle(e);
+            }
+        } catch (Throwable e) {
+            throw debug.handle(e);
+        } finally {
+            graph.checkCancellation();
+        }
+    }
+
+    @SuppressWarnings("try")
+    public static LIRGenerationResult emitLIR(Backend backend, StructuredGraph graph, Object stub, RegisterConfig registerConfig, LIRSuites lirSuites) {
+        String registerPressure = GraalOptions.RegisterPressure.getValue(graph.getOptions());
+        String[] allocationRestrictedTo = registerPressure == null ? null : registerPressure.split(",");
+        try {
+            return emitLIR0(backend, graph, stub, registerConfig, lirSuites, allocationRestrictedTo);
+        } catch (OutOfRegistersException e) {
+            if (allocationRestrictedTo != null) {
+                allocationRestrictedTo = null;
+                return emitLIR0(backend, graph, stub, registerConfig, lirSuites, allocationRestrictedTo);
+            }
+            /* If the re-execution fails we convert the exception into a "hard" failure */
+            throw new GraalError(e);
+        } finally {
+            graph.checkCancellation();
+        }
+    }
+
+    @SuppressWarnings("try")
+    private static LIRGenerationResult emitLIR0(Backend backend, StructuredGraph graph, Object stub, RegisterConfig registerConfig, LIRSuites lirSuites,
+                    String[] allocationRestrictedTo) {
+        DebugContext debug = graph.getDebug();
+        try (DebugContext.Scope ds = debug.scope("EmitLIR"); DebugCloseable a = EmitLIR.start(debug)) {
+            assert !graph.hasValueProxies();
+
+            ScheduleResult schedule = graph.getLastSchedule();
+            Block[] blocks = schedule.getCFG().getBlocks();
+            Block startBlock = schedule.getCFG().getStartBlock();
+            assert startBlock != null;
+            assert startBlock.getPredecessorCount() == 0;
+
+            AbstractBlockBase<?>[] codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blocks.length, startBlock);
+            AbstractBlockBase<?>[] linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blocks.length, startBlock);
+            LIR lir = new LIR(schedule.getCFG(), linearScanOrder, codeEmittingOrder, graph.getOptions(), graph.getDebug());
+
+            LIRGenerationProvider lirBackend = (LIRGenerationProvider) backend;
+            LIRGenerationResult lirGenRes = lirBackend.newLIRGenerationResult(graph.compilationId(), lir, registerConfig, graph, stub);
+            LIRGeneratorTool lirGen = lirBackend.newLIRGenerator(lirGenRes);
+            NodeLIRBuilderTool nodeLirGen = lirBackend.newNodeLIRBuilder(graph, lirGen);
+
+            // LIR generation
+            LIRGenerationContext context = new LIRGenerationContext(lirGen, nodeLirGen, graph, schedule);
+            new LIRGenerationPhase().apply(backend.getTarget(), lirGenRes, context);
+
+            try (DebugContext.Scope s = debug.scope("LIRStages", nodeLirGen, lirGenRes, lir)) {
+                // Dump LIR along with HIR (the LIR is looked up from context)
+                debug.dump(DebugContext.BASIC_LEVEL, graph.getLastSchedule(), "After LIR generation");
+                LIRGenerationResult result = emitLowLevel(backend.getTarget(), lirGenRes, lirGen, lirSuites, backend.newRegisterAllocationConfig(registerConfig, allocationRestrictedTo));
+                return result;
+            } catch (Throwable e) {
+                throw debug.handle(e);
+            }
+        } catch (Throwable e) {
+            throw debug.handle(e);
+        } finally {
+            graph.checkCancellation();
+        }
+    }
+
+    private static LIRGenerationResult emitLowLevel(TargetDescription target, LIRGenerationResult lirGenRes, LIRGeneratorTool lirGen, LIRSuites lirSuites,
+                    RegisterAllocationConfig registerAllocationConfig) {
+        DebugContext debug = lirGenRes.getLIR().getDebug();
+        PreAllocationOptimizationContext preAllocOptContext = new PreAllocationOptimizationContext(lirGen);
+        lirSuites.getPreAllocationOptimizationStage().apply(target, lirGenRes, preAllocOptContext);
+        debug.dump(DebugContext.BASIC_LEVEL, lirGenRes.getLIR(), "After PreAllocationOptimizationStage");
+
+        AllocationContext allocContext = new AllocationContext(lirGen.getSpillMoveFactory(), registerAllocationConfig);
+        lirSuites.getAllocationStage().apply(target, lirGenRes, allocContext);
+        debug.dump(DebugContext.BASIC_LEVEL, lirGenRes.getLIR(), "After AllocationStage");
+
+        PostAllocationOptimizationContext postAllocOptContext = new PostAllocationOptimizationContext(lirGen);
+        lirSuites.getPostAllocationOptimizationStage().apply(target, lirGenRes, postAllocOptContext);
+        debug.dump(DebugContext.BASIC_LEVEL, lirGenRes.getLIR(), "After PostAllocationOptimizationStage");
+
+        return lirGenRes;
+    }
+
+    @SuppressWarnings("try")
+    public static void emitCode(Backend backend,
+                    Assumptions assumptions,
+                    ResolvedJavaMethod rootMethod,
+                    Collection<ResolvedJavaMethod> inlinedMethods,
+                    EconomicSet<ResolvedJavaField> accessedFields,
+                    SpeculationLog speculationLog,
+                    int bytecodeSize,
+                    LIRGenerationResult lirGenRes,
+                    CompilationResult compilationResult,
+                    ResolvedJavaMethod installedCodeOwner,
+                    CompilationResultBuilderFactory factory) {
+        DebugContext debug = lirGenRes.getLIR().getDebug();
+        try (DebugCloseable a = EmitCode.start(debug)) {
+            LIRGenerationProvider lirBackend = (LIRGenerationProvider) backend;
+
+            FrameMap frameMap = lirGenRes.getFrameMap();
+            CompilationResultBuilder crb = lirBackend.newCompilationResultBuilder(lirGenRes, frameMap, compilationResult, factory);
+            lirBackend.emitCode(crb, lirGenRes.getLIR(), installedCodeOwner);
+            if (assumptions != null && !assumptions.isEmpty()) {
+                compilationResult.setAssumptions(assumptions.toArray());
+            }
+            if (rootMethod != null) {
+                compilationResult.setMethods(rootMethod, inlinedMethods);
+                compilationResult.setFields(accessedFields);
+                compilationResult.setBytecodeSize(bytecodeSize);
+            }
+            if (speculationLog != null) {
+                compilationResult.setSpeculationLog(speculationLog);
+            }
+            crb.finish();
+            if (debug.isCountEnabled()) {
+                List<DataPatch> ldp = compilationResult.getDataPatches();
+                JavaKind[] kindValues = JavaKind.values();
+                CounterKey[] dms = new CounterKey[kindValues.length];
+                for (int i = 0; i < dms.length; i++) {
+                    dms[i] = DebugContext.counter("DataPatches-%s", kindValues[i]);
+                }
+
+                for (DataPatch dp : ldp) {
+                    JavaKind kind = JavaKind.Illegal;
+                    if (dp.reference instanceof ConstantReference) {
+                        VMConstant constant = ((ConstantReference) dp.reference).getConstant();
+                        if (constant instanceof JavaConstant) {
+                            kind = ((JavaConstant) constant).getJavaKind();
+                        }
+                    }
+                    dms[kind.ordinal()].add(debug, 1);
+                }
+
+                DebugContext.counter("CompilationResults").increment(debug);
+                DebugContext.counter("CodeBytesEmitted").add(debug, compilationResult.getTargetCodeSize());
+                DebugContext.counter("InfopointsEmitted").add(debug, compilationResult.getInfopoints().size());
+                DebugContext.counter("DataPatches").add(debug, ldp.size());
+                DebugContext.counter("ExceptionHandlersEmitted").add(debug, compilationResult.getExceptionHandlers().size());
+            }
+
+            debug.dump(DebugContext.BASIC_LEVEL, compilationResult, "After code generation");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/LIRGenerationProvider.java	Tue Mar 12 19:17:42 2019 +0100
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 org.graalvm.compiler.core.gen;
+
+import org.graalvm.compiler.code.CompilationResult;
+import org.graalvm.compiler.core.common.CompilationIdentifier;
+import org.graalvm.compiler.lir.LIR;
+import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
+import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory;
+import org.graalvm.compiler.lir.framemap.FrameMap;
+import org.graalvm.compiler.lir.gen.LIRGenerationResult;
+import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
+
+import jdk.vm.ci.code.RegisterConfig;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
+/**
+ * Provides compiler backend-specific generation helpers for the {@link LIRCompilerBackend}.
+ */
+public interface LIRGenerationProvider {
+    LIRGeneratorTool newLIRGenerator(LIRGenerationResult lirGenRes);
+
+    LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, RegisterConfig registerConfig, StructuredGraph graph,
+                    Object stub);
+
+    NodeLIRBuilderTool newNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen);
+
+    /**
+     * Creates the object used to fill in the details of a given compilation result.
+     */
+    CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenResult, FrameMap frameMap, CompilationResult compilationResult,
+                    CompilationResultBuilderFactory factory);
+
+    /**
+     * Emits the code for a given graph.
+     *
+     * @param installedCodeOwner the method the compiled code will be associated with once
+     *            installed. This argument can be null.
+     */
+    void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner);
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java	Tue Mar 12 19:17:42 2019 +0100
@@ -768,4 +768,13 @@
     public LIRGeneratorTool getLIRGeneratorTool() {
         return gen;
     }
+
+    @Override
+    public void emitReadExceptionObject(ValueNode node) {
+        LIRGeneratorTool lirGenTool = getLIRGeneratorTool();
+        Value returnRegister = lirGenTool.getRegisterConfig().getReturnRegister(node.getStackKind()).asValue(
+                        LIRKind.fromJavaKind(lirGenTool.target().arch, node.getStackKind()));
+        lirGenTool.emitIncomingValues(new Value[]{returnRegister});
+        setResult(node, lirGenTool.emitMove(returnRegister));
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/HighTier.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/HighTier.java	Tue Mar 12 19:17:42 2019 +0100
@@ -47,7 +47,7 @@
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.phases.PhaseSuite;
 import org.graalvm.compiler.phases.common.CanonicalizerPhase;
-import org.graalvm.compiler.phases.common.ConvertDeoptimizeToGuardPhase;
+import org.graalvm.compiler.loop.phases.ConvertDeoptimizeToGuardPhase;
 import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase;
 import org.graalvm.compiler.phases.common.IncrementalCanonicalizerPhase;
 import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/LowTier.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/LowTier.java	Tue Mar 12 19:17:42 2019 +0100
@@ -39,6 +39,7 @@
 import org.graalvm.compiler.phases.common.ExpandLogicPhase;
 import org.graalvm.compiler.phases.common.FixReadsPhase;
 import org.graalvm.compiler.phases.common.LoweringPhase;
+import org.graalvm.compiler.phases.common.OptimizeDivPhase;
 import org.graalvm.compiler.phases.common.ProfileCompiledMethodsPhase;
 import org.graalvm.compiler.phases.common.PropagateDeoptimizeProbabilityPhase;
 import org.graalvm.compiler.phases.common.UseTrappingNullChecksPhase;
@@ -72,6 +73,8 @@
 
         appendPhase(new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.LOW_TIER));
 
+        appendPhase(new OptimizeDivPhase());
+
         appendPhase(new ExpandLogicPhase());
 
         appendPhase(new FixReadsPhase(true, new SchedulePhase(GraalOptions.StressTestEarlyReads.getValue(options) ? SchedulingStrategy.EARLIEST : SchedulingStrategy.LATEST_OUT_OF_LOOPS)));
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java	Tue Mar 12 19:17:42 2019 +0100
@@ -26,24 +26,17 @@
 
 import java.util.ArrayList;
 
-import jdk.internal.vm.compiler.collections.EconomicSet;
-import org.graalvm.compiler.asm.Assembler;
 import org.graalvm.compiler.code.CompilationResult;
 import org.graalvm.compiler.core.common.CompilationIdentifier;
 import org.graalvm.compiler.core.common.LIRKind;
 import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig;
 import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
 import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
+import org.graalvm.compiler.core.gen.LIRCompilerBackend;
 import org.graalvm.compiler.debug.DebugContext;
-import org.graalvm.compiler.lir.LIR;
-import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
 import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory;
-import org.graalvm.compiler.lir.framemap.FrameMap;
-import org.graalvm.compiler.lir.framemap.FrameMapBuilder;
-import org.graalvm.compiler.lir.gen.LIRGenerationResult;
-import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
+import org.graalvm.compiler.lir.phases.LIRSuites;
 import org.graalvm.compiler.nodes.StructuredGraph;
-import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.phases.tiers.SuitesProvider;
 import org.graalvm.compiler.phases.tiers.TargetProvider;
@@ -54,7 +47,6 @@
 import jdk.vm.ci.code.CompilationRequest;
 import jdk.vm.ci.code.CompiledCode;
 import jdk.vm.ci.code.InstalledCode;
-import jdk.vm.ci.code.Register;
 import jdk.vm.ci.code.RegisterConfig;
 import jdk.vm.ci.code.TargetDescription;
 import jdk.vm.ci.code.ValueKindFactory;
@@ -62,7 +54,6 @@
 import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.MetaAccessProvider;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
-import jdk.vm.ci.meta.SpeculationLog;
 
 /**
  * Represents a compiler backend for Graal.
@@ -117,12 +108,6 @@
     }
 
     /**
-     * The given registerConfig is optional, in case null is passed the default RegisterConfig from
-     * the CodeCacheProvider will be used.
-     */
-    public abstract FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig);
-
-    /**
      * Creates a new configuration for register allocation.
      *
      * @param allocationRestrictedTo if not {@code null}, register allocation will be restricted to
@@ -130,26 +115,6 @@
      */
     public abstract RegisterAllocationConfig newRegisterAllocationConfig(RegisterConfig registerConfig, String[] allocationRestrictedTo);
 
-    public abstract FrameMap newFrameMap(RegisterConfig registerConfig);
-
-    public abstract LIRGeneratorTool newLIRGenerator(LIRGenerationResult lirGenRes);
-
-    public abstract LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, FrameMapBuilder frameMapBuilder, StructuredGraph graph,
-                    Object stub);
-
-    public abstract NodeLIRBuilderTool newNodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool lirGen);
-
-    /**
-     * Creates the assembler used to emit the machine code.
-     */
-    protected abstract Assembler createAssembler(FrameMap frameMap);
-
-    /**
-     * Creates the object used to fill in the details of a given compilation result.
-     */
-    public abstract CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenResult, FrameMap frameMap, CompilationResult compilationResult,
-                    CompilationResultBuilderFactory factory);
-
     /**
      * Turns a Graal {@link CompilationResult} into a {@link CompiledCode} object that can be passed
      * to the VM for code installation.
@@ -158,21 +123,28 @@
 
     /**
      * @see #createInstalledCode(DebugContext, ResolvedJavaMethod, CompilationRequest,
-     *      CompilationResult, SpeculationLog, InstalledCode, boolean, Object[])
+     *      CompilationResult, InstalledCode, boolean, Object[])
      */
-    public InstalledCode createInstalledCode(DebugContext debug, ResolvedJavaMethod method, CompilationResult compilationResult,
-                    SpeculationLog speculationLog, InstalledCode predefinedInstalledCode, boolean isDefault) {
-        return createInstalledCode(debug, method, null, compilationResult, speculationLog, predefinedInstalledCode, isDefault, null);
+    public InstalledCode createInstalledCode(DebugContext debug,
+                    ResolvedJavaMethod method,
+                    CompilationResult compilationResult,
+                    InstalledCode predefinedInstalledCode,
+                    boolean isDefault) {
+        return createInstalledCode(debug, method, null, compilationResult, predefinedInstalledCode, isDefault, null);
     }
 
     /**
      * @see #createInstalledCode(DebugContext, ResolvedJavaMethod, CompilationRequest,
-     *      CompilationResult, SpeculationLog, InstalledCode, boolean, Object[])
+     *      CompilationResult, InstalledCode, boolean, Object[])
      */
     @SuppressWarnings("try")
-    public InstalledCode createInstalledCode(DebugContext debug, ResolvedJavaMethod method, CompilationRequest compilationRequest, CompilationResult compilationResult,
-                    SpeculationLog speculationLog, InstalledCode predefinedInstalledCode, boolean isDefault) {
-        return createInstalledCode(debug, method, compilationRequest, compilationResult, speculationLog, predefinedInstalledCode, isDefault, null);
+    public InstalledCode createInstalledCode(DebugContext debug,
+                    ResolvedJavaMethod method,
+                    CompilationRequest compilationRequest,
+                    CompilationResult compilationResult,
+                    InstalledCode predefinedInstalledCode,
+                    boolean isDefault) {
+        return createInstalledCode(debug, method, compilationRequest, compilationResult, predefinedInstalledCode, isDefault, null);
     }
 
     /**
@@ -185,7 +157,6 @@
      * @param predefinedInstalledCode a pre-allocated {@link InstalledCode} object to use as a
      *            reference to the installed code. If {@code null}, a new {@link InstalledCode}
      *            object will be created.
-     * @param speculationLog the speculation log to be used
      * @param isDefault specifies if the installed code should be made the default implementation of
      *            {@code compRequest.getMethod()}. The default implementation for a method is the
      *            code executed for standard calls to the method. This argument is ignored if
@@ -198,8 +169,13 @@
      *             {@link InstalledCode} object
      */
     @SuppressWarnings("try")
-    public InstalledCode createInstalledCode(DebugContext debug, ResolvedJavaMethod method, CompilationRequest compilationRequest, CompilationResult compilationResult,
-                    SpeculationLog speculationLog, InstalledCode predefinedInstalledCode, boolean isDefault, Object[] context) {
+    public InstalledCode createInstalledCode(DebugContext debug,
+                    ResolvedJavaMethod method,
+                    CompilationRequest compilationRequest,
+                    CompilationResult compilationResult,
+                    InstalledCode predefinedInstalledCode,
+                    boolean isDefault,
+                    Object[] context) {
         Object[] debugContext = context != null ? context : new Object[]{getProviders().getCodeCache(), method, compilationResult};
         CodeInstallationTask[] tasks;
         synchronized (this) {
@@ -215,7 +191,7 @@
             try {
                 preCodeInstallationTasks(tasks, compilationResult);
                 CompiledCode compiledCode = createCompiledCode(method, compilationRequest, compilationResult, isDefault, debug.getOptions());
-                installedCode = getProviders().getCodeCache().installCode(method, compiledCode, predefinedInstalledCode, speculationLog, isDefault);
+                installedCode = getProviders().getCodeCache().installCode(method, compiledCode, predefinedInstalledCode, compilationResult.getSpeculationLog(), isDefault);
                 assert predefinedInstalledCode == null || installedCode == predefinedInstalledCode;
             } catch (Throwable t) {
                 failCodeInstallationTasks(tasks, t);
@@ -259,12 +235,15 @@
      * @param method the method compiled to produce {@code compiledCode} or {@code null} if the
      *            input to {@code compResult} was not a {@link ResolvedJavaMethod}
      * @param compilationRequest the request or {@code null}
-     * @param compilationResult the code to be compiled
+     * @param compilationResult the compiled code
      * @return a reference to the compiled and ready-to-run installed code
      * @throws BailoutException if the code installation failed
      */
-    public InstalledCode addInstalledCode(DebugContext debug, ResolvedJavaMethod method, CompilationRequest compilationRequest, CompilationResult compilationResult) {
-        return createInstalledCode(debug, method, compilationRequest, compilationResult, null, null, false);
+    public InstalledCode addInstalledCode(DebugContext debug,
+                    ResolvedJavaMethod method,
+                    CompilationRequest compilationRequest,
+                    CompilationResult compilationResult) {
+        return createInstalledCode(debug, method, compilationRequest, compilationResult, null, false);
     }
 
     /**
@@ -273,30 +252,16 @@
      *
      * @param method the method compiled to produce {@code compiledCode} or {@code null} if the
      *            input to {@code compResult} was not a {@link ResolvedJavaMethod}
-     * @param compilationResult the code to be compiled
+     * @param compilationResult the compiled code
      * @return a reference to the compiled and ready-to-run installed code
      * @throws BailoutException if the code installation failed
      */
     public InstalledCode createDefaultInstalledCode(DebugContext debug, ResolvedJavaMethod method, CompilationResult compilationResult) {
-        return createInstalledCode(debug, method, compilationResult, null, null, true);
+        System.out.println(compilationResult.getSpeculationLog());
+        return createInstalledCode(debug, method, compilationResult, null, true);
     }
 
     /**
-     * Emits the code for a given graph.
-     *
-     * @param installedCodeOwner the method the compiled code will be associated with once
-     *            installed. This argument can be null.
-     */
-    public abstract void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner);
-
-    /**
-     * Translates a set of registers from the callee's perspective to the caller's perspective. This
-     * is needed for architectures where input/output registers are renamed during a call (e.g.
-     * register windows on SPARC). Registers which are not visible by the caller are removed.
-     */
-    public abstract EconomicSet<Register> translateToCallerRegisters(EconomicSet<Register> calleeRegisters);
-
-    /**
      * Gets the compilation id for a given {@link ResolvedJavaMethod}. Returns
      * {@code CompilationIdentifier#INVALID_COMPILATION_ID} in case there is no such id.
      *
@@ -306,6 +271,15 @@
         return CompilationIdentifier.INVALID_COMPILATION_ID;
     }
 
+    public void emitBackEnd(StructuredGraph graph,
+                    Object stub,
+                    ResolvedJavaMethod installedCodeOwner,
+                    CompilationResult compilationResult,
+                    CompilationResultBuilderFactory factory,
+                    RegisterConfig config, LIRSuites lirSuites) {
+        LIRCompilerBackend.emitBackEnd(graph, stub, installedCodeOwner, this, compilationResult, factory, config, lirSuites);
+    }
+
     /**
      * Encapsulates custom tasks done before and after code installation.
      */
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java	Tue Mar 12 19:17:42 2019 +0100
@@ -450,11 +450,11 @@
         }
     }
 
-    public Path getDumpPath(String extension, boolean directory) {
+    public Path getDumpPath(String extension, boolean createMissingDirectory) {
         try {
             String id = description == null ? null : description.identifier;
             String label = description == null ? null : description.getLabel();
-            Path result = PathUtilities.createUnique(immutable.options, DumpPath, id, label, extension, directory);
+            Path result = PathUtilities.createUnique(immutable.options, DumpPath, id, label, extension, createMissingDirectory);
             if (ShowDumpFiles.getValue(immutable.options)) {
                 TTY.println("Dumping debug output to %s", result.toAbsolutePath().toString());
             }
@@ -807,8 +807,9 @@
                 return true;
             }
             return !currentScope.isTopLevel();
+        } else {
+            return false;
         }
-        return immutable.scopesEnabled && currentScope == null;
     }
 
     class DisabledScope implements DebugContext.Scope {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugOptions.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugOptions.java	Tue Mar 12 19:17:42 2019 +0100
@@ -30,6 +30,7 @@
 import java.nio.file.Paths;
 
 import jdk.internal.vm.compiler.collections.EconomicMap;
+import org.graalvm.compiler.options.EnumOptionKey;
 import org.graalvm.compiler.options.Option;
 import org.graalvm.compiler.options.OptionKey;
 import org.graalvm.compiler.options.OptionType;
@@ -40,20 +41,28 @@
  * Options that configure a {@link DebugContext} and related functionality.
  */
 public class DebugOptions {
-    static class DeprecatedOptionKey<T> extends OptionKey<T> {
-        private final OptionKey<T> replacement;
 
-        DeprecatedOptionKey(OptionKey<T> replacement) {
-            super(replacement.getDefaultValue());
-            this.replacement = replacement;
-        }
+    /**
+     * Values for the {@link DebugOptions#PrintGraph} option denoting where graphs dumped as a
+     * result of the {@link DebugOptions#Dump} option are sent.
+     */
+    public enum PrintGraphTarget {
+        /**
+         * Dump graphs to files.
+         */
+        File,
 
-        @Override
-        protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, T oldValue, T newValue) {
-            // Ideally we'd use TTY here but it may not yet be initialized.
-            System.err.printf("Warning: the %s option is deprecated - use %s instead%n", getName(), replacement.getName());
-            replacement.update(values, newValue);
-        }
+        /**
+         * Dump graphs to the network. The network destination is specified by the
+         * {@link DebugOptions#PrintGraphHost} and {@link DebugOptions#PrintGraphPort} options. If a
+         * network connection cannot be opened, dumping falls back to {@link #File} dumping.
+         */
+        Network,
+
+        /**
+         * Do not dump graphs.
+         */
+        Disable;
     }
 
     // @formatter:off
@@ -118,7 +127,7 @@
     public static final OptionKey<Boolean> LogVerbose = new OptionKey<>(false);
 
     @Option(help = "The directory where various Graal dump files are written.")
-    public static final OptionKey<String> DumpPath = new OptionKey<>("dumps");
+    public static final OptionKey<String> DumpPath = new OptionKey<>("graal_dumps");
     @Option(help = "Print the name of each dump file path as it's created.")
     public static final OptionKey<Boolean> ShowDumpFiles = new OptionKey<>(false);
 
@@ -127,15 +136,30 @@
     @Option(help = "Enable dumping LIR, register allocation and code generation info to the C1Visualizer.", type = OptionType.Debug)
     public static final OptionKey<Boolean> PrintBackendCFG = new OptionKey<>(true);
 
-    @Option(help = "Enable dumping to the IdealGraphVisualizer.", type = OptionType.Debug)
-    public static final OptionKey<Boolean> PrintGraph = new OptionKey<>(true);
-    @Option(help = "Print graphs to files instead of sending them over the network.", type = OptionType.Debug)
-    public static final OptionKey<Boolean> PrintGraphFile = new OptionKey<>(false);
+    @Option(help = "file:doc-files/PrintGraphHelp.txt", type = OptionType.Debug)
+    public static final EnumOptionKey<PrintGraphTarget> PrintGraph = new EnumOptionKey<>(PrintGraphTarget.File);
+
+    @Option(help = "Setting to true sets PrintGraph=file, setting to false sets PrintGraph=network", type = OptionType.Debug)
+    public static final OptionKey<Boolean> PrintGraphFile = new OptionKey<Boolean>(true) {
+        @Override
+        protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, Boolean oldValue, Boolean newValue) {
+            PrintGraphTarget v = PrintGraph.getValueOrDefault(values);
+            if (newValue.booleanValue()) {
+                if (v != PrintGraphTarget.File) {
+                    PrintGraph.update(values, PrintGraphTarget.File);
+                }
+            } else {
+                if (v != PrintGraphTarget.Network) {
+                    PrintGraph.update(values, PrintGraphTarget.Network);
+                }
+            }
+        }
+    };
 
     @Option(help = "Host part of the address to which graphs are dumped.", type = OptionType.Debug)
     public static final OptionKey<String> PrintGraphHost = new OptionKey<>("127.0.0.1");
     @Option(help = "Port part of the address to which graphs are dumped in binary format.", type = OptionType.Debug)
-    public static final OptionKey<Integer> PrintBinaryGraphPort = new OptionKey<>(4445);
+    public static final OptionKey<Integer> PrintGraphPort = new OptionKey<>(4445);
     @Option(help = "Schedule graphs as they are dumped.", type = OptionType.Debug)
     public static final OptionKey<Boolean> PrintGraphWithSchedule = new OptionKey<>(false);
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/IgvDumpChannel.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/IgvDumpChannel.java	Tue Mar 12 19:17:42 2019 +0100
@@ -24,6 +24,10 @@
 
 package org.graalvm.compiler.debug;
 
+import static org.graalvm.compiler.debug.DebugOptions.PrintGraphHost;
+import static org.graalvm.compiler.debug.DebugOptions.PrintGraphPort;
+
+import java.io.File;
 import java.io.IOException;
 import java.io.InterruptedIOException;
 import java.net.InetSocketAddress;
@@ -35,10 +39,12 @@
 import java.nio.file.Path;
 import java.nio.file.StandardOpenOption;
 import java.util.function.Supplier;
-import static org.graalvm.compiler.debug.DebugOptions.PrintBinaryGraphPort;
-import static org.graalvm.compiler.debug.DebugOptions.PrintGraphHost;
+
+import org.graalvm.compiler.debug.DebugOptions.PrintGraphTarget;
 import org.graalvm.compiler.options.OptionValues;
 
+import jdk.vm.ci.common.NativeImageReinitialize;
+
 final class IgvDumpChannel implements WritableByteChannel {
     private final Supplier<Path> pathProvider;
     private final OptionValues options;
@@ -52,7 +58,8 @@
 
     @Override
     public int write(ByteBuffer src) throws IOException {
-        return channel().write(src);
+        WritableByteChannel channel = channel();
+        return channel == null ? 0 : channel.write(src);
     }
 
     @Override
@@ -77,10 +84,13 @@
             throw new IOException();
         }
         if (sharedChannel == null) {
-            if (DebugOptions.PrintGraphFile.getValue(options)) {
-                sharedChannel = createFileChannel(pathProvider);
+            PrintGraphTarget target = DebugOptions.PrintGraph.getValue(options);
+            if (target == PrintGraphTarget.File) {
+                sharedChannel = createFileChannel(pathProvider, null);
+            } else if (target == PrintGraphTarget.Network) {
+                sharedChannel = createNetworkChannel(pathProvider, options);
             } else {
-                sharedChannel = createNetworkChannel(pathProvider, options);
+                TTY.println("WARNING: Graph dumping requested but value of %s option is %s", DebugOptions.PrintGraph.getName(), PrintGraphTarget.Disable);
             }
         }
         return sharedChannel;
@@ -88,10 +98,11 @@
 
     private static WritableByteChannel createNetworkChannel(Supplier<Path> pathProvider, OptionValues options) throws IOException {
         String host = PrintGraphHost.getValue(options);
-        int port = PrintBinaryGraphPort.getValue(options);
+        int port = PrintGraphPort.getValue(options);
         try {
             WritableByteChannel channel = SocketChannel.open(new InetSocketAddress(host, port));
-            TTY.println("Connected to the IGV on %s:%d", host, port);
+            String targetAnnouncement = String.format("Connected to the IGV on %s:%d", host, port);
+            maybeAnnounceTarget(targetAnnouncement);
             return channel;
         } catch (ClosedByInterruptException | InterruptedIOException e) {
             /*
@@ -101,18 +112,39 @@
              */
             return null;
         } catch (IOException e) {
-            if (!DebugOptions.PrintGraphFile.hasBeenSet(options)) {
-                return createFileChannel(pathProvider);
+            String networkFailure = String.format("Could not connect to the IGV on %s:%d", host, port);
+            if (pathProvider != null) {
+                return createFileChannel(pathProvider, networkFailure);
             } else {
-                throw new IOException(String.format("Could not connect to the IGV on %s:%d", host, port), e);
+                throw new IOException(networkFailure, e);
             }
         }
     }
 
-    private static WritableByteChannel createFileChannel(Supplier<Path> pathProvider) throws IOException {
+    @NativeImageReinitialize private static String lastTargetAnnouncement;
+
+    private static void maybeAnnounceTarget(String targetAnnouncement) {
+        if (!targetAnnouncement.equals(lastTargetAnnouncement)) {
+            // Ignore races - an extra announcement is ok
+            lastTargetAnnouncement = targetAnnouncement;
+            TTY.println(targetAnnouncement);
+        }
+    }
+
+    private static WritableByteChannel createFileChannel(Supplier<Path> pathProvider, String networkFailure) throws IOException {
         Path path = pathProvider.get();
         try {
-            return FileChannel.open(path, StandardOpenOption.WRITE, StandardOpenOption.CREATE);
+            FileChannel channel = FileChannel.open(path, StandardOpenOption.WRITE, StandardOpenOption.CREATE);
+            File dir = path.toFile();
+            if (!dir.isDirectory()) {
+                dir = dir.getParentFile();
+            }
+            if (networkFailure == null) {
+                maybeAnnounceTarget("Dumping IGV graphs in " + dir);
+            } else {
+                maybeAnnounceTarget(networkFailure + ". Dumping IGV graphs in " + dir);
+            }
+            return channel;
         } catch (IOException e) {
             throw new IOException(String.format("Failed to open %s to dump IGV graphs", path), e);
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/PathUtilities.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/PathUtilities.java	Tue Mar 12 19:17:42 2019 +0100
@@ -84,7 +84,7 @@
 
     private static final String ELLIPSIS = "...";
 
-    static Path createUnique(OptionValues options, OptionKey<String> baseNameOption, String id, String label, String ext, boolean createDirectory) throws IOException {
+    static Path createUnique(OptionValues options, OptionKey<String> baseNameOption, String id, String label, String ext, boolean createMissingDirectory) throws IOException {
         String uniqueTag = "";
         int dumpCounter = 1;
         String prefix;
@@ -118,7 +118,7 @@
             Path dumpDir = DebugOptions.getDumpDirectory(options);
             Path result = Paths.get(dumpDir.toString(), fileName);
             try {
-                if (createDirectory) {
+                if (createMissingDirectory) {
                     return Files.createDirectory(result);
                 } else {
                     try {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/doc-files/PrintGraphHelp.txt	Tue Mar 12 19:17:42 2019 +0100
@@ -0,0 +1,6 @@
+Where IdealGraphVisualizer graph dumps triggered by Dump or DumpOnError should be written.
+The accepted values are:
+      File - Dump IGV graphs to the local file system (see DumpPath).
+   Network - Dump IGV graphs to the network destination specified by PrintGraphHost and PrintGraphPort.
+             If a network connection cannot be opened, dumping falls back to file dumping. 
+   Disable - Do not dump IGV graphs.
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/graphio/GraphOutputTest.java	Tue Mar 12 19:17:42 2019 +0100
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 org.graalvm.compiler.graph.test.graphio;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.WritableByteChannel;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Objects;
+import org.graalvm.graphio.GraphOutput;
+import org.graalvm.graphio.GraphStructure;
+import org.junit.Test;
+
+public final class GraphOutputTest {
+
+    @Test
+    @SuppressWarnings("static-method")
+    public void testWritableByteChannel() throws IOException {
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        WritableByteChannel channel = Channels.newChannel(out);
+        ByteBuffer data = generateData(1 << 17);
+        GraphOutput<?, ?> graphOutput = GraphOutput.newBuilder(new MockGraphStructure()).protocolVersion(6, 0).embedded(true).build(channel);
+        try (GraphOutput<?, ?> closable = graphOutput) {
+            assertTrue(closable.isOpen());
+            closable.write(data);
+        }
+        assertFalse(graphOutput.isOpen());
+        assertArrayEquals(data.array(), out.toByteArray());
+    }
+
+    @Test
+    @SuppressWarnings("static-method")
+    public void testWriteDuringPrint() throws IOException {
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        WritableByteChannel channel = Channels.newChannel(out);
+        class Action implements Runnable {
+            GraphOutput<MockGraph, ?> out;
+
+            @Override
+            public void run() {
+                try {
+                    ByteBuffer data = ByteBuffer.allocate(16);
+                    data.limit(16);
+                    out.write(data);
+                } catch (IOException ioe) {
+                    throw new RuntimeException(ioe);
+                }
+            }
+        }
+        Action action = new Action();
+        try (GraphOutput<MockGraph, ?> graphOutput = GraphOutput.newBuilder(new MockGraphStructure(action)).protocolVersion(6, 0).build(channel)) {
+            action.out = graphOutput;
+            try {
+                graphOutput.print(new MockGraph(), Collections.emptyMap(), 0, "Mock Graph");
+                fail("Expected IllegalStateException");
+            } catch (IllegalStateException ise) {
+                // expected exception
+            }
+        }
+    }
+
+    @Test
+    @SuppressWarnings("static-method")
+    public void testEmbeddedWritableByteChannel() throws IOException {
+        ByteArrayOutputStream expected = new ByteArrayOutputStream();
+        WritableByteChannel expectedChannel = Channels.newChannel(expected);
+        Map<Object, Object> properties = Collections.singletonMap("version.id", 1);
+        try (GraphOutput<MockGraph, ?> graphOutput = GraphOutput.newBuilder(new MockGraphStructure()).protocolVersion(6, 0).build(expectedChannel)) {
+            graphOutput.print(new MockGraph(), properties, 1, "Graph 1");
+            graphOutput.write(ByteBuffer.allocate(0));
+            graphOutput.print(new MockGraph(), properties, 2, "Graph 1");
+        }
+        ByteArrayOutputStream embedded = new ByteArrayOutputStream();
+        SharedWritableByteChannel embeddChannel = new SharedWritableByteChannel(Channels.newChannel(embedded));
+        try {
+            try (GraphOutput<MockGraph, ?> baseOutput = GraphOutput.newBuilder(new MockGraphStructure()).protocolVersion(6, 0).build(embeddChannel)) {
+                try (GraphOutput<MockGraph, ?> embeddedOutput = GraphOutput.newBuilder(new MockGraphStructure()).protocolVersion(6, 0).embedded(true).build((WritableByteChannel) baseOutput)) {
+                    embeddedOutput.print(new MockGraph(), properties, 1, "Graph 1");
+                    baseOutput.print(new MockGraph(), properties, 2, "Graph 1");
+                }
+            }
+        } finally {
+            embeddChannel.realClose();
+        }
+        assertArrayEquals(expected.toByteArray(), embedded.toByteArray());
+    }
+
+    private static ByteBuffer generateData(int size) {
+        ByteBuffer buffer = ByteBuffer.allocate(size);
+        for (int i = 0; i < size; i++) {
+            buffer.put(i, (byte) i);
+        }
+        buffer.limit(size);
+        return buffer;
+    }
+
+    private static final class SharedWritableByteChannel implements WritableByteChannel {
+
+        private final WritableByteChannel delegate;
+
+        SharedWritableByteChannel(WritableByteChannel delegate) {
+            Objects.requireNonNull(delegate, "Delegate must be non null.");
+            this.delegate = delegate;
+        }
+
+        @Override
+        public int write(ByteBuffer bb) throws IOException {
+            return delegate.write(bb);
+        }
+
+        @Override
+        public boolean isOpen() {
+            return delegate.isOpen();
+        }
+
+        @Override
+        public void close() throws IOException {
+        }
+
+        void realClose() throws IOException {
+            delegate.close();
+        }
+    }
+
+    private static final class MockGraphStructure implements GraphStructure<MockGraph, Void, Void, Void> {
+
+        private final Runnable enterAction;
+
+        MockGraphStructure() {
+            this.enterAction = null;
+        }
+
+        MockGraphStructure(Runnable enterAction) {
+            this.enterAction = enterAction;
+        }
+
+        @Override
+        public MockGraph graph(MockGraph currentGraph, Object obj) {
+            onEnter();
+            return null;
+        }
+
+        @Override
+        public Iterable<? extends Void> nodes(MockGraph graph) {
+            onEnter();
+            return Collections.emptySet();
+        }
+
+        @Override
+        public int nodesCount(MockGraph graph) {
+            onEnter();
+            return 0;
+        }
+
+        @Override
+        public int nodeId(Void node) {
+            onEnter();
+            return 0;
+        }
+
+        @Override
+        public boolean nodeHasPredecessor(Void node) {
+            onEnter();
+            return false;
+        }
+
+        @Override
+        public void nodeProperties(MockGraph graph, Void node, Map<String, ? super Object> properties) {
+            onEnter();
+        }
+
+        @Override
+        public Void node(Object obj) {
+            onEnter();
+            return null;
+        }
+
+        @Override
+        public Void nodeClass(Object obj) {
+            onEnter();
+            return null;
+        }
+
+        @Override
+        public Void classForNode(Void node) {
+            onEnter();
+            return null;
+        }
+
+        @Override
+        public String nameTemplate(Void nodeClass) {
+            onEnter();
+            return null;
+        }
+
+        @Override
+        public Object nodeClassType(Void nodeClass) {
+            onEnter();
+            return null;
+        }
+
+        @Override
+        public Void portInputs(Void nodeClass) {
+            onEnter();
+            return null;
+        }
+
+        @Override
+        public Void portOutputs(Void nodeClass) {
+            onEnter();
+            return null;
+        }
+
+        @Override
+        public int portSize(Void port) {
+            onEnter();
+            return 0;
+        }
+
+        @Override
+        public boolean edgeDirect(Void port, int index) {
+            onEnter();
+            return false;
+        }
+
+        @Override
+        public String edgeName(Void port, int index) {
+            onEnter();
+            return null;
+        }
+
+        @Override
+        public Object edgeType(Void port, int index) {
+            onEnter();
+            return null;
+        }
+
+        @Override
+        public Collection<? extends Void> edgeNodes(MockGraph graph, Void node, Void port, int index) {
+            onEnter();
+            return null;
+        }
+
+        private void onEnter() {
+            if (enterAction != null) {
+                enterAction.run();
+            }
+        }
+    }
+
+    private static final class MockGraph {
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java	Tue Mar 12 19:17:42 2019 +0100
@@ -24,9 +24,7 @@
 
 package org.graalvm.compiler.graph;
 
-import static org.graalvm.compiler.core.common.Fields.translateInto;
 import static org.graalvm.compiler.debug.GraalError.shouldNotReachHere;
-import static org.graalvm.compiler.graph.Edges.translateInto;
 import static org.graalvm.compiler.graph.Graph.isModificationCountsEnabled;
 import static org.graalvm.compiler.graph.InputEdges.translateInto;
 import static org.graalvm.compiler.graph.Node.WithAllEdges;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java	Tue Mar 12 19:17:42 2019 +0100
@@ -36,6 +36,7 @@
 
 import jdk.internal.vm.compiler.collections.EconomicSet;
 import org.graalvm.compiler.asm.Assembler;
+import org.graalvm.compiler.asm.BranchTargetOutOfBoundsException;
 import org.graalvm.compiler.asm.Label;
 import org.graalvm.compiler.asm.aarch64.AArch64Address;
 import org.graalvm.compiler.asm.aarch64.AArch64Assembler;
@@ -47,6 +48,7 @@
 import org.graalvm.compiler.core.common.LIRKind;
 import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig;
 import org.graalvm.compiler.core.common.spi.ForeignCallLinkage;
+import org.graalvm.compiler.core.gen.LIRGenerationProvider;
 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
 import org.graalvm.compiler.hotspot.HotSpotDataBuilder;
 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
@@ -86,21 +88,16 @@
 /**
  * HotSpot AArch64 specific backend.
  */
-public class AArch64HotSpotBackend extends HotSpotHostBackend {
+public class AArch64HotSpotBackend extends HotSpotHostBackend implements LIRGenerationProvider {
 
     public AArch64HotSpotBackend(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, HotSpotProviders providers) {
         super(config, runtime, providers);
     }
 
-    @Override
-    public FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig) {
+    private FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig) {
         RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig;
-        return new AArch64FrameMapBuilder(newFrameMap(registerConfigNonNull), getCodeCache(), registerConfigNonNull);
-    }
-
-    @Override
-    public FrameMap newFrameMap(RegisterConfig registerConfig) {
-        return new AArch64FrameMap(getCodeCache(), registerConfig, this);
+        FrameMap frameMap = new AArch64FrameMap(getCodeCache(), registerConfigNonNull, this);
+        return new AArch64FrameMapBuilder(frameMap, getCodeCache(), registerConfigNonNull);
     }
 
     @Override
@@ -109,8 +106,9 @@
     }
 
     @Override
-    public LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, FrameMapBuilder frameMapBuilder, StructuredGraph graph, Object stub) {
-        return new HotSpotLIRGenerationResult(compilationId, lir, frameMapBuilder, makeCallingConvention(graph, (Stub) stub), stub, config.requiresReservedStackCheck(graph.getMethods()));
+    public LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, RegisterConfig registerConfig, StructuredGraph graph, Object stub) {
+        return new HotSpotLIRGenerationResult(compilationId, lir, newFrameMapBuilder(registerConfig), makeCallingConvention(graph, (Stub) stub), stub,
+                        config.requiresReservedStackCheck(graph.getMethods()));
     }
 
     @Override
@@ -219,18 +217,13 @@
     }
 
     @Override
-    protected Assembler createAssembler(FrameMap frameMap) {
-        return new AArch64MacroAssembler(getTarget());
-    }
-
-    @Override
     public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRen, FrameMap frameMap, CompilationResult compilationResult, CompilationResultBuilderFactory factory) {
         HotSpotLIRGenerationResult gen = (HotSpotLIRGenerationResult) lirGenRen;
         LIR lir = gen.getLIR();
         assert gen.getDeoptimizationRescueSlot() == null || frameMap.frameNeedsAllocating() : "method that can deoptimize must have a frame";
 
         Stub stub = gen.getStub();
-        Assembler masm = createAssembler(frameMap);
+        Assembler masm = new AArch64MacroAssembler(getTarget());
         HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null);
 
         DataBuilder dataBuilder = new HotSpotDataBuilder(getCodeCache().getTarget());
@@ -252,11 +245,25 @@
 
     @Override
     public void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner) {
+        Label verifiedStub = new Label();
+        crb.buildLabelOffsets(lir);
+        try {
+            emitCode(crb, lir, installedCodeOwner, verifiedStub);
+        } catch (BranchTargetOutOfBoundsException e) {
+            // A branch estimation was wrong, now retry with conservative label ranges, this
+            // should always work
+            crb.setConservativeLabelRanges();
+            crb.resetForEmittingCode();
+            lir.resetLabels();
+            verifiedStub.reset();
+            emitCode(crb, lir, installedCodeOwner, verifiedStub);
+        }
+    }
+
+    private void emitCode(CompilationResultBuilder crb, LIR lir, ResolvedJavaMethod installedCodeOwner, Label verifiedStub) {
         AArch64MacroAssembler masm = (AArch64MacroAssembler) crb.asm;
         FrameMap frameMap = crb.frameMap;
         RegisterConfig regConfig = frameMap.getRegisterConfig();
-        Label verifiedStub = new Label();
-
         emitCodePrefix(crb, installedCodeOwner, masm, regConfig, verifiedStub);
         emitCodeBody(crb, lir, masm);
         emitCodeSuffix(crb, masm, frameMap);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotJumpToExceptionHandlerInCallerOp.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotJumpToExceptionHandlerInCallerOp.java	Tue Mar 12 19:17:42 2019 +0100
@@ -37,7 +37,7 @@
 import org.graalvm.compiler.lir.LIRInstructionClass;
 import org.graalvm.compiler.lir.Opcode;
 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
-import org.graalvm.compiler.serviceprovider.GraalServices;
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
 
 import jdk.vm.ci.code.Register;
 import jdk.vm.ci.meta.AllocatableValue;
@@ -71,7 +71,7 @@
     public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
         leaveFrame(crb, masm, /* emitSafepoint */false, false);
 
-        if (GraalServices.JAVA_SPECIFICATION_VERSION < 8) {
+        if (JavaVersionUtil.JAVA_SPECIFICATION_VERSION < 8) {
             // Restore sp from fp if the exception PC is a method handle call site.
             try (ScratchRegister sc = masm.getScratchRegister()) {
                 Register scratch = sc.getRegister();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/BinaryMathStubTest.java	Tue Mar 12 19:17:42 2019 +0100
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 org.graalvm.compiler.hotspot.amd64.test;
+
+import static org.junit.Assume.assumeTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.graalvm.compiler.api.test.Graal;
+import org.graalvm.compiler.core.test.GraalCompilerTest;
+import org.graalvm.compiler.runtime.RuntimeProvider;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import jdk.vm.ci.amd64.AMD64;
+import jdk.vm.ci.code.Architecture;
+
+@RunWith(Parameterized.class)
+public class BinaryMathStubTest extends GraalCompilerTest {
+
+    @Parameterized.Parameters(name = "{0}")
+    public static List<Object[]> data() {
+        ArrayList<Object[]> ret = new ArrayList<>();
+        ret.add(new Object[]{"pow"});
+        return ret;
+    }
+
+    private static final double[] inputs = {0.0D, Math.PI / 2, Math.PI, -1.0D, Double.MAX_VALUE, Double.MIN_VALUE, Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY};
+    private final String stub;
+
+    public BinaryMathStubTest(String stub) {
+        this.stub = stub;
+    }
+
+    @Before
+    public void checkAMD64() {
+        Architecture arch = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getTarget().arch;
+        assumeTrue("skipping AMD64 specific test", arch instanceof AMD64);
+    }
+
+    public static double pow(double x, double y) {
+        return Math.pow(x, y);
+    }
+
+    @Test
+    public void testStub() {
+        for (double x : inputs) {
+            for (double y : inputs) {
+                test(stub, x, y);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/UnaryMathStubTest.java	Tue Mar 12 19:17:42 2019 +0100
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 org.graalvm.compiler.hotspot.amd64.test;
+
+import static org.junit.Assume.assumeTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.graalvm.compiler.api.test.Graal;
+import org.graalvm.compiler.core.test.GraalCompilerTest;
+import org.graalvm.compiler.runtime.RuntimeProvider;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import jdk.vm.ci.amd64.AMD64;
+import jdk.vm.ci.code.Architecture;
+
+@RunWith(Parameterized.class)
+public class UnaryMathStubTest extends GraalCompilerTest {
+
+    @Parameterized.Parameters(name = "{0}")
+    public static List<Object[]> data() {
+        ArrayList<Object[]> ret = new ArrayList<>();
+        ret.add(new Object[]{"sin"});
+        ret.add(new Object[]{"cos"});
+        ret.add(new Object[]{"tan"});
+        ret.add(new Object[]{"exp"});
+        ret.add(new Object[]{"log"});
+        ret.add(new Object[]{"log10"});
+        return ret;
+    }
+
+    private static final double[] inputs = {0.0D, Math.PI / 2, Math.PI, -1.0D, Double.MAX_VALUE, Double.MIN_VALUE, Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY};
+    private final String stub;
+
+    public UnaryMathStubTest(String stub) {
+        this.stub = stub;
+    }
+
+    @Before
+    public void checkAMD64() {
+        Architecture arch = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getTarget().arch;
+        assumeTrue("skipping AMD64 specific test", arch instanceof AMD64);
+    }
+
+    public static double sin(double value) {
+        return Math.sin(value);
+    }
+
+    public static double cos(double value) {
+        return Math.cos(value);
+    }
+
+    public static double tan(double value) {
+        return Math.tan(value);
+    }
+
+    public static double exp(double value) {
+        return Math.exp(value);
+    }
+
+    public static double log(double value) {
+        return Math.log(value);
+    }
+
+    public static double log10(double value) {
+        return Math.log10(value);
+    }
+
+    @Test
+    public void testStub() {
+        for (double input : inputs) {
+            test(stub, input);
+        }
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java	Tue Mar 12 19:17:42 2019 +0100
@@ -199,7 +199,7 @@
                 CountedLoopInfo countedLoopInfo = loop.counted();
                 IntegerStamp initStamp = (IntegerStamp) inductionVariable.initNode().stamp(NodeView.DEFAULT);
                 if (initStamp.isPositive()) {
-                    if (inductionVariable.isConstantExtremum()) {
+                    if (inductionVariable.isConstantExtremum() && countedLoopInfo.counterNeverOverflows()) {
                         long init = inductionVariable.constantInit();
                         long stride = inductionVariable.constantStride();
                         long extremum = inductionVariable.constantExtremum();
@@ -211,7 +211,9 @@
                             }
                         }
                     }
-                    if (countedLoopInfo.getCounter() == inductionVariable && inductionVariable.direction() == InductionVariable.Direction.Up && countedLoopInfo.getOverFlowGuard() != null) {
+                    if (countedLoopInfo.getCounter() == inductionVariable &&
+                                    inductionVariable.direction() == InductionVariable.Direction.Up &&
+                                    (countedLoopInfo.getOverFlowGuard() != null || countedLoopInfo.counterNeverOverflows())) {
                         return graph.unique(new ZeroExtendNode(input, INT_BITS, ADDRESS_BITS, true));
                     }
                 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java	Tue Mar 12 19:17:42 2019 +0100
@@ -43,7 +43,7 @@
 import org.graalvm.compiler.core.common.CompilationIdentifier;
 import org.graalvm.compiler.core.common.LIRKind;
 import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig;
-import org.graalvm.compiler.core.target.Backend;
+import org.graalvm.compiler.core.gen.LIRGenerationProvider;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
 import org.graalvm.compiler.hotspot.HotSpotDataBuilder;
@@ -85,21 +85,16 @@
 /**
  * HotSpot AMD64 specific backend.
  */
-public class AMD64HotSpotBackend extends HotSpotHostBackend {
+public class AMD64HotSpotBackend extends HotSpotHostBackend implements LIRGenerationProvider {
 
     public AMD64HotSpotBackend(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, HotSpotProviders providers) {
         super(config, runtime, providers);
     }
 
-    @Override
-    public FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig) {
+    private FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig) {
         RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig;
-        return new AMD64FrameMapBuilder(newFrameMap(registerConfigNonNull), getCodeCache(), registerConfigNonNull);
-    }
-
-    @Override
-    public FrameMap newFrameMap(RegisterConfig registerConfig) {
-        return new AMD64FrameMap(getCodeCache(), registerConfig, this);
+        FrameMap frameMap = new AMD64FrameMap(getCodeCache(), registerConfigNonNull, this);
+        return new AMD64FrameMapBuilder(frameMap, getCodeCache(), registerConfigNonNull);
     }
 
     @Override
@@ -108,8 +103,9 @@
     }
 
     @Override
-    public LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, FrameMapBuilder frameMapBuilder, StructuredGraph graph, Object stub) {
-        return new HotSpotLIRGenerationResult(compilationId, lir, frameMapBuilder, makeCallingConvention(graph, (Stub) stub), stub, config.requiresReservedStackCheck(graph.getMethods()));
+    public LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, RegisterConfig registerConfig, StructuredGraph graph, Object stub) {
+        return new HotSpotLIRGenerationResult(compilationId, lir, newFrameMapBuilder(registerConfig), makeCallingConvention(graph, (Stub) stub), stub,
+                        config.requiresReservedStackCheck(graph.getMethods()));
     }
 
     @Override
@@ -196,11 +192,6 @@
     }
 
     @Override
-    protected Assembler createAssembler(FrameMap frameMap) {
-        return new AMD64MacroAssembler(getTarget());
-    }
-
-    @Override
     public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRen, FrameMap frameMap, CompilationResult compilationResult, CompilationResultBuilderFactory factory) {
         // Omit the frame if the method:
         // - has no spill slots or other slots allocated during register allocation
@@ -216,7 +207,7 @@
         boolean omitFrame = CanOmitFrame.getValue(options) && !frameMap.frameNeedsAllocating() && !lir.hasArgInCallerFrame() && !gen.hasForeignCall();
 
         Stub stub = gen.getStub();
-        Assembler masm = createAssembler(frameMap);
+        Assembler masm = new AMD64MacroAssembler(getTarget());
         HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null, omitFrame);
         DataBuilder dataBuilder = new HotSpotDataBuilder(getCodeCache().getTarget());
         CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, dataBuilder, frameContext, options, debug, compilationResult, Register.None);
@@ -258,7 +249,7 @@
     /**
      * Emits the code prior to the verified entry point.
      *
-     * @param installedCodeOwner see {@link Backend#emitCode}
+     * @param installedCodeOwner see {@link LIRGenerationProvider#emitCode}
      */
     public void emitCodePrefix(ResolvedJavaMethod installedCodeOwner, CompilationResultBuilder crb, AMD64MacroAssembler asm, RegisterConfig regConfig, Label verifiedEntry) {
         HotSpotProviders providers = getProviders();
@@ -309,14 +300,14 @@
     /**
      * Emits the code which starts at the verified entry point.
      *
-     * @param installedCodeOwner see {@link Backend#emitCode}
+     * @param installedCodeOwner see {@link LIRGenerationProvider#emitCode}
      */
     public void emitCodeBody(ResolvedJavaMethod installedCodeOwner, CompilationResultBuilder crb, LIR lir) {
         crb.emit(lir);
     }
 
     /**
-     * @param installedCodeOwner see {@link Backend#emitCode}
+     * @param installedCodeOwner see {@link LIRGenerationProvider#emitCode}
      */
     public void emitCodeSuffix(ResolvedJavaMethod installedCodeOwner, CompilationResultBuilder crb, AMD64MacroAssembler asm, FrameMap frameMap) {
         HotSpotProviders providers = getProviders();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java	Tue Mar 12 19:17:42 2019 +0100
@@ -25,7 +25,6 @@
 package org.graalvm.compiler.hotspot.amd64;
 
 import static jdk.vm.ci.common.InitTimer.timer;
-import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -141,7 +140,7 @@
                 replacements = createReplacements(options, p, snippetReflection, bytecodeProvider);
             }
             try (InitTimer rt = timer("create GraphBuilderPhase plugins")) {
-                plugins = createGraphBuilderPlugins(compilerConfiguration, config, options, target, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes);
+                plugins = createGraphBuilderPlugins(compilerConfiguration, config, target, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes);
                 replacements.setGraphBuilderPlugins(plugins);
             }
             try (InitTimer rt = timer("create Suites provider")) {
@@ -157,11 +156,11 @@
         }
     }
 
-    protected Plugins createGraphBuilderPlugins(CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, OptionValues options, TargetDescription target,
+    protected Plugins createGraphBuilderPlugins(CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, TargetDescription target,
                     HotSpotConstantReflectionProvider constantReflection, HotSpotHostForeignCallsProvider foreignCalls, HotSpotMetaAccessProvider metaAccess,
                     HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes) {
         Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, replacements);
-        AMD64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), (AMD64) target.arch, GraalArithmeticStubs.getValue(options), false);
+        AMD64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), (AMD64) target.arch, false);
         return plugins;
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java	Tue Mar 12 19:17:42 2019 +0100
@@ -30,6 +30,7 @@
 import static jdk.vm.ci.meta.Value.ILLEGAL;
 import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER;
 import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER;
+import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs;
 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.JUMP_ADDRESS;
 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Reexecutability.REEXECUTABLE;
 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Reexecutability.REEXECUTABLE_ONLY_AFTER_EXCEPTION;
@@ -38,10 +39,16 @@
 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NOFP;
 import static org.graalvm.compiler.hotspot.replacements.CRC32CSubstitutions.UPDATE_BYTES_CRC32C;
 import static org.graalvm.compiler.hotspot.replacements.CRC32Substitutions.UPDATE_BYTES_CRC32;
+import static org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode.BinaryOperation.POW;
+import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.COS;
+import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.EXP;
+import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.LOG;
+import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.LOG10;
+import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.SIN;
+import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.TAN;
 import static jdk.internal.vm.compiler.word.LocationIdentity.any;
 
 import org.graalvm.compiler.core.common.LIRKind;
-import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
 import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkageImpl;
 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
@@ -62,14 +69,6 @@
 
 public class AMD64HotSpotForeignCallsProvider extends HotSpotHostForeignCallsProvider {
 
-    public static final ForeignCallDescriptor ARITHMETIC_SIN_STUB = new ForeignCallDescriptor("arithmeticSinStub", double.class, double.class);
-    public static final ForeignCallDescriptor ARITHMETIC_COS_STUB = new ForeignCallDescriptor("arithmeticCosStub", double.class, double.class);
-    public static final ForeignCallDescriptor ARITHMETIC_TAN_STUB = new ForeignCallDescriptor("arithmeticTanStub", double.class, double.class);
-    public static final ForeignCallDescriptor ARITHMETIC_EXP_STUB = new ForeignCallDescriptor("arithmeticExpStub", double.class, double.class);
-    public static final ForeignCallDescriptor ARITHMETIC_POW_STUB = new ForeignCallDescriptor("arithmeticPowStub", double.class, double.class, double.class);
-    public static final ForeignCallDescriptor ARITHMETIC_LOG_STUB = new ForeignCallDescriptor("arithmeticLogStub", double.class, double.class);
-    public static final ForeignCallDescriptor ARITHMETIC_LOG10_STUB = new ForeignCallDescriptor("arithmeticLog10Stub", double.class, double.class);
-
     private final Value[] nativeABICallerSaveRegisters;
 
     public AMD64HotSpotForeignCallsProvider(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalRuntimeProvider runtime, MetaAccessProvider metaAccess, CodeCacheProvider codeCache,
@@ -93,14 +92,6 @@
         register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, exceptionCc, null, any()));
         register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, exceptionCc, null, any()));
 
-        link(new AMD64MathStub(ARITHMETIC_LOG_STUB, options, providers, registerStubCall(ARITHMETIC_LOG_STUB, LEAF, REEXECUTABLE, NO_LOCATIONS)));
-        link(new AMD64MathStub(ARITHMETIC_LOG10_STUB, options, providers, registerStubCall(ARITHMETIC_LOG10_STUB, LEAF, REEXECUTABLE, NO_LOCATIONS)));
-        link(new AMD64MathStub(ARITHMETIC_SIN_STUB, options, providers, registerStubCall(ARITHMETIC_SIN_STUB, LEAF, REEXECUTABLE, NO_LOCATIONS)));
-        link(new AMD64MathStub(ARITHMETIC_COS_STUB, options, providers, registerStubCall(ARITHMETIC_COS_STUB, LEAF, REEXECUTABLE, NO_LOCATIONS)));
-        link(new AMD64MathStub(ARITHMETIC_TAN_STUB, options, providers, registerStubCall(ARITHMETIC_TAN_STUB, LEAF, REEXECUTABLE, NO_LOCATIONS)));
-        link(new AMD64MathStub(ARITHMETIC_EXP_STUB, options, providers, registerStubCall(ARITHMETIC_EXP_STUB, LEAF, REEXECUTABLE, NO_LOCATIONS)));
-        link(new AMD64MathStub(ARITHMETIC_POW_STUB, options, providers, registerStubCall(ARITHMETIC_POW_STUB, LEAF, REEXECUTABLE, NO_LOCATIONS)));
-
         if (config.useCRC32Intrinsics) {
             // This stub does callee saving
             registerForeignCall(UPDATE_BYTES_CRC32, config.updateBytesCRC32Stub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any());
@@ -138,4 +129,19 @@
         return nativeABICallerSaveRegisters;
     }
 
+    @Override
+    protected void registerMathStubs(GraalHotSpotVMConfig hotSpotVMConfig, HotSpotProviders providers, OptionValues options) {
+        if (GraalArithmeticStubs.getValue(options)) {
+            link(new AMD64MathStub(SIN, options, providers, registerStubCall(SIN.foreignCallDescriptor, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+            link(new AMD64MathStub(COS, options, providers, registerStubCall(COS.foreignCallDescriptor, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+            link(new AMD64MathStub(TAN, options, providers, registerStubCall(TAN.foreignCallDescriptor, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+            link(new AMD64MathStub(EXP, options, providers, registerStubCall(EXP.foreignCallDescriptor, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+            link(new AMD64MathStub(LOG, options, providers, registerStubCall(LOG.foreignCallDescriptor, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+            link(new AMD64MathStub(LOG10, options, providers, registerStubCall(LOG10.foreignCallDescriptor, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+            link(new AMD64MathStub(POW, options, providers, registerStubCall(POW.foreignCallDescriptor, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+        } else {
+            super.registerMathStubs(hotSpotVMConfig, providers, options);
+        }
+    }
+
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java	Tue Mar 12 19:17:42 2019 +0100
@@ -24,10 +24,10 @@
 
 package org.graalvm.compiler.hotspot.amd64;
 
-import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
 import static jdk.vm.ci.amd64.AMD64.rbp;
 import static jdk.vm.ci.amd64.AMD64.rsp;
 import static jdk.vm.ci.code.ValueUtil.asRegister;
+import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
 
 import org.graalvm.compiler.asm.amd64.AMD64Address;
 import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag;
@@ -35,7 +35,7 @@
 import org.graalvm.compiler.lir.LIRInstructionClass;
 import org.graalvm.compiler.lir.Opcode;
 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
-import org.graalvm.compiler.serviceprovider.GraalServices;
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
 
 import jdk.vm.ci.code.Register;
 import jdk.vm.ci.meta.AllocatableValue;
@@ -71,7 +71,7 @@
         // Discard the return address, thus completing restoration of caller frame
         masm.incrementq(rsp, 8);
 
-        if (GraalServices.JAVA_SPECIFICATION_VERSION < 8) {
+        if (JavaVersionUtil.JAVA_SPECIFICATION_VERSION < 8) {
             // Restore rsp from rbp if the exception PC is a method handle call site.
             AMD64Address dst = new AMD64Address(thread, isMethodHandleReturnOffset);
             masm.cmpl(dst, 0);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Tue Mar 12 19:17:42 2019 +0100
@@ -118,7 +118,7 @@
     }
 
     private AMD64HotSpotLIRGenerator(HotSpotProviders providers, GraalHotSpotVMConfig config, LIRGenerationResult lirGenRes, BackupSlotProvider backupSlotProvider) {
-        this(new AMD64HotSpotLIRKindTool(), new AMD64ArithmeticLIRGenerator(null, new AMD64HotSpotMaths()), new AMD64HotSpotMoveFactory(backupSlotProvider), providers, config, lirGenRes);
+        this(new AMD64HotSpotLIRKindTool(), new AMD64ArithmeticLIRGenerator(null), new AMD64HotSpotMoveFactory(backupSlotProvider), providers, config, lirGenRes);
     }
 
     protected AMD64HotSpotLIRGenerator(LIRKindTool lirKindTool, AMD64ArithmeticLIRGenerator arithmeticLIRGen, MoveFactory moveFactory, HotSpotProviders providers, GraalHotSpotVMConfig config,
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java	Tue Mar 12 19:17:42 2019 +0100
@@ -25,15 +25,8 @@
 package org.graalvm.compiler.hotspot.amd64;
 
 import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs;
-import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_COS_STUB;
-import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_EXP_STUB;
-import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_LOG10_STUB;
-import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_LOG_STUB;
-import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_POW_STUB;
-import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_SIN_STUB;
-import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_TAN_STUB;
 
-import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
+import org.graalvm.compiler.api.replacements.Snippet;
 import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
 import org.graalvm.compiler.debug.DebugHandlersFactory;
 import org.graalvm.compiler.graph.Node;
@@ -44,21 +37,26 @@
 import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider;
 import org.graalvm.compiler.hotspot.nodes.profiling.ProfileNode;
 import org.graalvm.compiler.hotspot.replacements.profiling.ProbabilisticProfileSnippets;
+import org.graalvm.compiler.nodes.StructuredGraph;
 import org.graalvm.compiler.nodes.calc.FloatConvertNode;
+import org.graalvm.compiler.nodes.extended.ForeignCallNode;
 import org.graalvm.compiler.nodes.spi.LoweringTool;
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.replacements.amd64.AMD64ConvertSnippets;
-import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode.BinaryOperation;
+import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode;
 import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation;
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
 
 import jdk.vm.ci.code.TargetDescription;
 import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider;
 import jdk.vm.ci.meta.MetaAccessProvider;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
 
 public class AMD64HotSpotLoweringProvider extends DefaultHotSpotLoweringProvider {
 
     private AMD64ConvertSnippets.Templates convertSnippets;
     private ProbabilisticProfileSnippets.Templates profileSnippets;
+    private AMD64X87MathSnippets.Templates mathSnippets;
 
     public AMD64HotSpotLoweringProvider(HotSpotGraalRuntimeProvider runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers,
                     HotSpotConstantReflectionProvider constantReflection, TargetDescription target) {
@@ -68,9 +66,10 @@
     @Override
     public void initialize(OptionValues options, Iterable<DebugHandlersFactory> factories, HotSpotProviders providers, GraalHotSpotVMConfig config) {
         convertSnippets = new AMD64ConvertSnippets.Templates(options, factories, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget());
-        profileSnippets = ProfileNode.Options.ProbabilisticProfiling.getValue(options)
+        profileSnippets = ProfileNode.Options.ProbabilisticProfiling.getValue(options) && !JavaVersionUtil.Java8OrEarlier
                         ? new ProbabilisticProfileSnippets.Templates(options, factories, providers, providers.getCodeCache().getTarget())
                         : null;
+        mathSnippets = new AMD64X87MathSnippets.Templates(options, factories, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget());
         super.initialize(options, factories, providers, config);
     }
 
@@ -80,47 +79,49 @@
             convertSnippets.lower((FloatConvertNode) n, tool);
         } else if (profileSnippets != null && n instanceof ProfileNode) {
             profileSnippets.lower((ProfileNode) n, tool);
+        } else if (n instanceof UnaryMathIntrinsicNode) {
+            lowerUnaryMath((UnaryMathIntrinsicNode) n, tool);
         } else {
             super.lower(n, tool);
         }
     }
 
-    @Override
-    protected ForeignCallDescriptor toForeignCall(UnaryOperation operation) {
-        if (GraalArithmeticStubs.getValue(runtime.getOptions())) {
-            switch (operation) {
+    private void lowerUnaryMath(UnaryMathIntrinsicNode math, LoweringTool tool) {
+        if (tool.getLoweringStage() == LoweringTool.StandardLoweringStage.HIGH_TIER) {
+            return;
+        }
+        StructuredGraph graph = math.graph();
+        ResolvedJavaMethod method = graph.method();
+        if (method != null) {
+            if (method.getAnnotation(Snippet.class) != null) {
+                // In the context of SnippetStub, i.e., Graal-generated stubs, use the LIR
+                // lowering to emit the stub assembly code instead of the Node lowering.
+                return;
+            }
+        }
+        if (!GraalArithmeticStubs.getValue(graph.getOptions())) {
+            switch (math.getOperation()) {
+                case SIN:
+                case COS:
+                case TAN:
+                    // Math.sin(), .cos() and .tan() guarantee a value within 1 ULP of the exact
+                    // result, but x87 trigonometric FPU instructions are only that accurate within
+                    // [-pi/4, pi/4]. The snippets fall back to a foreign call to HotSpot stubs
+                    // should the inputs outside of that interval.
+                    mathSnippets.lower(math, tool);
+                    return;
                 case LOG:
-                    return ARITHMETIC_LOG_STUB;
+                    math.replaceAtUsages(graph.addOrUnique(new AMD64X87MathIntrinsicNode(math.getValue(), UnaryOperation.LOG)));
+                    return;
                 case LOG10:
-                    return ARITHMETIC_LOG10_STUB;
-                case SIN:
-                    return ARITHMETIC_SIN_STUB;
-                case COS:
-                    return ARITHMETIC_COS_STUB;
-                case TAN:
-                    return ARITHMETIC_TAN_STUB;
-                case EXP:
-                    return ARITHMETIC_EXP_STUB;
+                    math.replaceAtUsages(graph.addOrUnique(new AMD64X87MathIntrinsicNode(math.getValue(), UnaryOperation.LOG10)));
+                    return;
             }
-        } else if (operation == UnaryOperation.EXP) {
-            return operation.foreignCallDescriptor;
         }
-        // Lower only using LIRGenerator
-        return null;
-    }
 
-    @Override
-    protected ForeignCallDescriptor toForeignCall(BinaryOperation operation) {
-        if (GraalArithmeticStubs.getValue(runtime.getOptions())) {
-            switch (operation) {
-                case POW:
-                    return ARITHMETIC_POW_STUB;
-            }
-        } else if (operation == BinaryOperation.POW) {
-            return operation.foreignCallDescriptor;
-        }
-        // Lower only using LIRGenerator
-        return null;
+        ForeignCallNode call = graph.add(new ForeignCallNode(foreignCalls, math.getOperation().foreignCallDescriptor, math.getValue()));
+        graph.addAfterFixed(tool.lastFixedNode(), call);
+        math.replaceAtUsages(call);
     }
 
     @Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMaths.java	Tue Mar 12 12:12:01 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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 org.graalvm.compiler.hotspot.amd64;
-
-import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs;
-import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.COS;
-import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.LOG;
-import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.LOG10;
-import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.SIN;
-import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.TAN;
-
-import org.graalvm.compiler.core.amd64.AMD64ArithmeticLIRGenerator;
-import org.graalvm.compiler.core.common.LIRKind;
-import org.graalvm.compiler.hotspot.HotSpotBackend.Options;
-import org.graalvm.compiler.lir.Variable;
-import org.graalvm.compiler.lir.gen.LIRGenerator;
-
-import jdk.vm.ci.meta.Value;
-
-/**
- * Lowering of selected {@link Math} routines that depends on the value of
- * {@link Options#GraalArithmeticStubs}.
- */
-public class AMD64HotSpotMaths implements AMD64ArithmeticLIRGenerator.Maths {
-
-    @Override
-    public Variable emitLog(LIRGenerator gen, Value input, boolean base10) {
-        if (GraalArithmeticStubs.getValue(gen.getResult().getLIR().getOptions())) {
-            return null;
-        }
-        Variable result = gen.newVariable(LIRKind.combine(input));
-        gen.append(new AMD64HotSpotMathIntrinsicOp(base10 ? LOG10 : LOG, result, gen.asAllocatable(input)));
-        return result;
-    }
-
-    @Override
-    public Variable emitCos(LIRGenerator gen, Value input) {
-        if (GraalArithmeticStubs.getValue(gen.getResult().getLIR().getOptions())) {
-            return null;
-        }
-        Variable result = gen.newVariable(LIRKind.combine(input));
-        gen.append(new AMD64HotSpotMathIntrinsicOp(COS, result, gen.asAllocatable(input)));
-        return result;
-    }
-
-    @Override
-    public Variable emitSin(LIRGenerator gen, Value input) {
-        if (GraalArithmeticStubs.getValue(gen.getResult().getLIR().getOptions())) {
-            return null;
-        }
-        Variable result = gen.newVariable(LIRKind.combine(input));
-        gen.append(new AMD64HotSpotMathIntrinsicOp(SIN, result, gen.asAllocatable(input)));
-        return result;
-    }
-
-    @Override
-    public Variable emitTan(LIRGenerator gen, Value input) {
-        if (GraalArithmeticStubs.getValue(gen.getResult().getLIR().getOptions())) {
-            return null;
-        }
-        Variable result = gen.newVariable(LIRKind.combine(input));
-        gen.append(new AMD64HotSpotMathIntrinsicOp(TAN, result, gen.asAllocatable(input)));
-        return result;
-    }
-
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64MathStub.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64MathStub.java	Tue Mar 12 19:17:42 2019 +0100
@@ -24,16 +24,8 @@
 
 package org.graalvm.compiler.hotspot.amd64;
 
-import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_COS_STUB;
-import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_EXP_STUB;
-import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_LOG10_STUB;
-import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_LOG_STUB;
-import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_POW_STUB;
-import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_SIN_STUB;
-import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_TAN_STUB;
-
 import org.graalvm.compiler.api.replacements.Snippet;
-import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
+import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
 import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
 import org.graalvm.compiler.hotspot.stubs.SnippetStub;
@@ -48,33 +40,38 @@
  */
 public class AMD64MathStub extends SnippetStub {
 
-    public AMD64MathStub(ForeignCallDescriptor descriptor, OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) {
-        super(snippetName(descriptor), options, providers, linkage);
+    public AMD64MathStub(UnaryOperation operation, OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) {
+        super(snippetName(operation), options, providers, linkage);
     }
 
-    private static String snippetName(ForeignCallDescriptor descriptor) {
-        if (descriptor == ARITHMETIC_LOG_STUB) {
-            return "log";
+    public AMD64MathStub(BinaryOperation operation, OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) {
+        super(snippetName(operation), options, providers, linkage);
+    }
+
+    private static String snippetName(UnaryOperation operation) {
+        switch (operation) {
+            case SIN:
+                return "sin";
+            case COS:
+                return "cos";
+            case TAN:
+                return "tan";
+            case EXP:
+                return "exp";
+            case LOG:
+                return "log";
+            case LOG10:
+                return "log10";
+            default:
+                throw GraalError.shouldNotReachHere("Unknown operation " + operation);
         }
-        if (descriptor == ARITHMETIC_LOG10_STUB) {
-            return "log10";
-        }
-        if (descriptor == ARITHMETIC_SIN_STUB) {
-            return "sin";
-        }
-        if (descriptor == ARITHMETIC_COS_STUB) {
-            return "cos";
-        }
-        if (descriptor == ARITHMETIC_TAN_STUB) {
-            return "tan";
-        }
-        if (descriptor == ARITHMETIC_EXP_STUB) {
-            return "exp";
-        }
-        if (descriptor == ARITHMETIC_POW_STUB) {
+    }
+
+    private static String snippetName(BinaryOperation operation) {
+        if (operation == BinaryOperation.POW) {
             return "pow";
         }
-        throw new InternalError("Unknown operation " + descriptor);
+        throw GraalError.shouldNotReachHere("Unknown operation " + operation);
     }
 
     @Snippet
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64X87MathIntrinsicNode.java	Tue Mar 12 19:17:42 2019 +0100
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 org.graalvm.compiler.hotspot.amd64;
+
+import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.COS;
+import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.LOG;
+import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.LOG10;
+import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.SIN;
+import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.TAN;
+import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_64;
+import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
+
+import org.graalvm.compiler.core.common.LIRKind;
+import org.graalvm.compiler.core.common.type.FloatStamp;
+import org.graalvm.compiler.core.common.type.PrimitiveStamp;
+import org.graalvm.compiler.core.common.type.Stamp;
+import org.graalvm.compiler.debug.GraalError;
+import org.graalvm.compiler.graph.NodeClass;
+import org.graalvm.compiler.graph.spi.CanonicalizerTool;
+import org.graalvm.compiler.lir.Variable;
+import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
+import org.graalvm.compiler.nodeinfo.NodeInfo;
+import org.graalvm.compiler.nodes.ConstantNode;
+import org.graalvm.compiler.nodes.NodeView;
+import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.calc.UnaryNode;
+import org.graalvm.compiler.nodes.spi.LIRLowerable;
+import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
+import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation;
+
+import jdk.vm.ci.meta.Value;
+
+@NodeInfo(nameTemplate = "X87MathIntrinsic#{p#operation/s}", cycles = CYCLES_64, size = SIZE_1)
+public final class AMD64X87MathIntrinsicNode extends UnaryNode implements LIRLowerable {
+
+    public static final NodeClass<AMD64X87MathIntrinsicNode> TYPE = NodeClass.create(AMD64X87MathIntrinsicNode.class);
+    protected final UnaryOperation operation;
+
+    protected AMD64X87MathIntrinsicNode(ValueNode value, UnaryOperation op) {
+        super(TYPE, op.computeStamp(value.stamp(NodeView.DEFAULT)), value);
+        assert value.stamp(NodeView.DEFAULT) instanceof FloatStamp && PrimitiveStamp.getBits(value.stamp(NodeView.DEFAULT)) == 64;
+        this.operation = op;
+    }
+
+    @Override
+    public Stamp foldStamp(Stamp valueStamp) {
+        return operation.computeStamp(valueStamp);
+    }
+
+    @Override
+    public void generate(NodeLIRBuilderTool generator) {
+        LIRGeneratorTool gen = generator.getLIRGeneratorTool();
+        Value input = generator.operand(getValue());
+        Variable result = gen.newVariable(LIRKind.combine(input));
+
+        switch (operation) {
+            case SIN:
+                gen.append(new AMD64HotSpotMathIntrinsicOp(SIN, result, gen.asAllocatable(input)));
+                break;
+            case COS:
+                gen.append(new AMD64HotSpotMathIntrinsicOp(COS, result, gen.asAllocatable(input)));
+                break;
+            case TAN:
+                gen.append(new AMD64HotSpotMathIntrinsicOp(TAN, result, gen.asAllocatable(input)));
+                break;
+            case LOG:
+                gen.append(new AMD64HotSpotMathIntrinsicOp(LOG, result, gen.asAllocatable(input)));
+                break;
+            case LOG10:
+                gen.append(new AMD64HotSpotMathIntrinsicOp(LOG10, result, gen.asAllocatable(input)));
+                break;
+            default:
+                throw GraalError.shouldNotReachHere();
+        }
+        generator.setResult(this, result);
+    }
+
+    @Override
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
+        if (forValue.isConstant()) {
+            return ConstantNode.forDouble(operation.compute(forValue.asJavaConstant().asDouble()));
+        }
+        return this;
+    }
+
+    @NodeIntrinsic
+    public static native double compute(double value, @ConstantNodeParameter UnaryOperation op);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64X87MathSnippets.java	Tue Mar 12 19:17:42 2019 +0100
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 org.graalvm.compiler.hotspot.amd64;
+
+import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER;
+
+import org.graalvm.compiler.api.replacements.Snippet;
+import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
+import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
+import org.graalvm.compiler.debug.DebugHandlersFactory;
+import org.graalvm.compiler.debug.GraalError;
+import org.graalvm.compiler.graph.Node.ConstantNodeParameter;
+import org.graalvm.compiler.graph.Node.NodeIntrinsic;
+import org.graalvm.compiler.nodes.extended.ForeignCallNode;
+import org.graalvm.compiler.nodes.spi.LoweringTool;
+import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.phases.util.Providers;
+import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates;
+import org.graalvm.compiler.replacements.SnippetTemplate.Arguments;
+import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo;
+import org.graalvm.compiler.replacements.Snippets;
+import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode;
+import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation;
+
+import jdk.vm.ci.code.TargetDescription;
+
+public class AMD64X87MathSnippets implements Snippets {
+
+    private static final double PI_4 = Math.PI / 4;
+
+    @Snippet
+    public static double sin(double input) {
+        if (Math.abs(input) < PI_4) {
+            return AMD64X87MathIntrinsicNode.compute(input, UnaryOperation.SIN);
+        }
+        return callDouble1(UnaryOperation.SIN.foreignCallDescriptor, input);
+    }
+
+    @Snippet
+    public static double cos(double input) {
+        if (Math.abs(input) < PI_4) {
+            return AMD64X87MathIntrinsicNode.compute(input, UnaryOperation.COS);
+        }
+        return callDouble1(UnaryOperation.COS.foreignCallDescriptor, input);
+    }
+
+    @Snippet
+    public static double tan(double input) {
+        if (Math.abs(input) < PI_4) {
+            return AMD64X87MathIntrinsicNode.compute(input, UnaryOperation.TAN);
+        }
+        return callDouble1(UnaryOperation.TAN.foreignCallDescriptor, input);
+    }
+
+    @NodeIntrinsic(value = ForeignCallNode.class)
+    private static native double callDouble1(@ConstantNodeParameter ForeignCallDescriptor descriptor, double value);
+
+    public static class Templates extends AbstractTemplates {
+
+        private final SnippetInfo sin;
+        private final SnippetInfo cos;
+        private final SnippetInfo tan;
+
+        public Templates(OptionValues options, Iterable<DebugHandlersFactory> factories, Providers providers, SnippetReflectionProvider snippetReflection, TargetDescription target) {
+            super(options, factories, providers, snippetReflection, target);
+
+            sin = snippet(AMD64X87MathSnippets.class, "sin");
+            cos = snippet(AMD64X87MathSnippets.class, "cos");
+            tan = snippet(AMD64X87MathSnippets.class, "tan");
+        }
+
+        public void lower(UnaryMathIntrinsicNode mathIntrinsicNode, LoweringTool tool) {
+            SnippetInfo info;
+
+            switch (mathIntrinsicNode.getOperation()) {
+                case SIN:
+                    info = sin;
+                    break;
+                case COS:
+                    info = cos;
+                    break;
+                case TAN:
+                    info = tan;
+                    break;
+                default:
+                    throw GraalError.shouldNotReachHere("Snippet not found for math intrinsic " + mathIntrinsicNode.getOperation().name());
+            }
+
+            Arguments args = new Arguments(info, mathIntrinsicNode.graph().getGuardsStage(), tool.getLoweringStage());
+            args.add("input", mathIntrinsicNode.getValue());
+            template(mathIntrinsicNode, args).instantiate(providers.getMetaAccess(), mathIntrinsicNode, DEFAULT_REPLACER, tool, args);
+            mathIntrinsicNode.safeDelete();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.jdk9.test/src/org/graalvm/compiler/hotspot/jdk9/test/StringUTF16ToBytesGetCharsTest.java	Tue Mar 12 19:17:42 2019 +0100
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 org.graalvm.compiler.hotspot.jdk9.test;
+
+import static org.junit.Assume.assumeFalse;
+
+import jdk.vm.ci.code.InstalledCode;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import org.graalvm.compiler.core.common.CompilationIdentifier;
+import org.graalvm.compiler.hotspot.replacements.StringUTF16Substitutions;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.java.NewArrayNode;
+import org.graalvm.compiler.replacements.arraycopy.ArrayCopyCallNode;
+import org.graalvm.compiler.replacements.test.MethodSubstitutionTest;
+import org.graalvm.compiler.test.AddExports;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Test substitutions for (innate) methods StringUTF16.toBytes and StringUTF16.getChars provided by
+ * {@link StringUTF16Substitutions}.
+ */
+@AddExports({"java.base/java.lang"})
+public final class StringUTF16ToBytesGetCharsTest extends MethodSubstitutionTest {
+
+    private static final int N = 1000;
+    private static final int N_OVERFLOW = 10;
+
+    @Before
+    public void checkAMD64() {
+        assumeFalse(Java8OrEarlier);
+    }
+
+    @Test
+    public void testStringUTF16ToBytes() throws ClassNotFoundException {
+        Class<?> javaclass = Class.forName("java.lang.StringUTF16");
+
+        ResolvedJavaMethod caller = getResolvedJavaMethod(javaclass, "toBytes", char[].class, int.class, int.class);
+        StructuredGraph graph = getReplacements().getIntrinsicGraph(caller, CompilationIdentifier.INVALID_COMPILATION_ID, getDebugContext());
+        assertInGraph(graph, NewArrayNode.class);
+        assertInGraph(graph, ArrayCopyCallNode.class);
+
+        InstalledCode code = getCode(caller, graph);
+
+        for (int srcOffset = 0; srcOffset < 2; srcOffset++) {
+            for (int i = 0; i < N; i++) {
+                int length = i2sz(i);
+                char[] src = fillUTF16Chars(new char[length]);
+                int copiedLength = Math.max(0, length - srcOffset);
+                int srcDelta = Math.min(srcOffset, copiedLength);
+                byte[] dst = (byte[]) invokeSafe(caller, null, src, srcDelta, copiedLength);
+                assert dst.length == copiedLength * 2;
+                byte[] dst2 = (byte[]) executeVarargsSafe(code, src, srcDelta, copiedLength);
+                assertDeepEquals(dst, dst2);
+            }
+        }
+        for (int srcOff = 0; srcOff < N_OVERFLOW; ++srcOff) {
+            for (int len = 0; len < N_OVERFLOW; ++len) {
+                char[] src = fillUTF16Chars(new char[N_OVERFLOW]);
+                test(caller, null, src, srcOff, len);
+            }
+        }
+    }
+
+    @Test
+    public void testStringUTF16getChars() throws ClassNotFoundException {
+        Class<?> javaclass = Class.forName("java.lang.StringUTF16");
+
+        ResolvedJavaMethod caller = getResolvedJavaMethod(javaclass, "getChars", byte[].class, int.class, int.class, char[].class, int.class);
+        StructuredGraph graph = getReplacements().getIntrinsicGraph(caller, CompilationIdentifier.INVALID_COMPILATION_ID, getDebugContext());
+        assertInGraph(graph, ArrayCopyCallNode.class);
+
+        InstalledCode code = getCode(caller, graph);
+
+        for (int dstOffset = 0; dstOffset < 2; dstOffset++) {
+            for (int srcOffset = 0; srcOffset < 2; srcOffset++) {
+                for (int i = 0; i < N; i++) {
+                    int length = i2sz(i);
+                    byte[] src = fillUTF16Bytes(new byte[length * 2]);
+                    char[] dst = new char[length];
+                    int copiedLength = Math.max(0, length - Math.max(dstOffset, srcOffset));
+                    int dstDelta = Math.min(dstOffset, copiedLength);
+                    int srcDelta = Math.min(srcOffset, copiedLength);
+                    invokeSafe(caller, null, src, srcDelta, srcDelta + copiedLength, dst, dstDelta);
+                    char[] dst2 = new char[length];
+                    executeVarargsSafe(code, src, srcDelta, srcDelta + copiedLength, dst2, dstDelta);
+                    assertDeepEquals(dst, dst2);
+                }
+            }
+        }
+        for (int srcOff = 0; srcOff < N_OVERFLOW; ++srcOff) {
+            for (int dstOff = 0; dstOff < N_OVERFLOW; ++dstOff) {
+                for (int len = 0; len < N_OVERFLOW; ++len) {
+                    byte[] src = fillUTF16Bytes(new byte[N_OVERFLOW]);
+                    char[] dst = new char[N_OVERFLOW];
+                    test(caller, null, src, srcOff, len, dst, dstOff);
+                }
+            }
+        }
+    }
+
+    private static char[] fillUTF16Chars(char[] v) {
+        for (int ch = 0, i = 0; i < v.length; i++, ch += 0x101) {
+            v[i] = (char) ch;
+        }
+        return v;
+    }
+
+    private static byte[] fillUTF16Bytes(byte[] v) {
+        for (int ch = 1, i = 0; i < v.length; i += 2, ch++) {
+            v[i] = (byte) (ch - 1);
+            v[i + 1] = (byte) ch;
+        }
+        return v;
+    }
+
+    private static int i2sz(int i) {
+        return i * 3;
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.lir.test/src/org/graalvm/compiler/hotspot/lir/test/BenchmarkCounterOverflowTest.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.lir.test/src/org/graalvm/compiler/hotspot/lir/test/BenchmarkCounterOverflowTest.java	Tue Mar 12 19:17:42 2019 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,9 +27,12 @@
 import static org.graalvm.compiler.test.SubprocessUtil.getVMCommandLine;
 import static org.graalvm.compiler.test.SubprocessUtil.withoutDebuggerArguments;
 
+import java.io.File;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import org.graalvm.compiler.api.directives.GraalDirectives;
 import org.graalvm.compiler.core.common.LIRKind;
@@ -121,6 +124,7 @@
         Assert.assertNotEquals("Expected non-zero exit status", 0, proc.exitCode);
 
         Iterator<String> it = proc.output.iterator();
+        boolean foundProblematicFrame = false;
         while (it.hasNext()) {
             String line = it.next();
             if (line.contains("Problematic frame:")) {
@@ -130,11 +134,34 @@
                 }
                 line = it.next();
                 if (line.contains(BenchmarkCounterOverflowTest.class.getName() + ".test")) {
-                    return;
+                    foundProblematicFrame = true;
+                    break;
                 }
                 Assert.fail("Unexpected stack trace: " + line);
             }
         }
-        Assert.fail(String.format("Could not find method in output:%n%s", proc));
+        // find and delete hserr file
+        while (it.hasNext()) {
+            String line = it.next();
+            if (line.contains("An error report file with more information is saved as:")) {
+                if (!it.hasNext()) {
+                    // no more line
+                    break;
+                }
+                line = it.next();
+                Pattern pattern = Pattern.compile("^# (.*hs_err_pid.*log)$");
+                Matcher matcher = pattern.matcher(line);
+                if (matcher.matches()) {
+                    File hserrFile = new File(matcher.group(1));
+                    if (hserrFile.exists()) {
+                        if (VERBOSE) {
+                            System.out.println("Deleting error report file:" + hserrFile.getAbsolutePath());
+                        }
+                        hserrFile.delete();
+                    }
+                }
+            }
+        }
+        Assert.assertTrue(String.format("Could not find method in output:%n%s", proc), foundProblematicFrame);
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackend.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackend.java	Tue Mar 12 19:17:42 2019 +0100
@@ -63,6 +63,7 @@
 import org.graalvm.compiler.core.common.CompilationIdentifier;
 import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig;
 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
+import org.graalvm.compiler.core.gen.LIRGenerationProvider;
 import org.graalvm.compiler.core.sparc.SPARCNodeMatchRules;
 import org.graalvm.compiler.debug.CounterKey;
 import org.graalvm.compiler.debug.DebugContext;
@@ -109,7 +110,7 @@
 /**
  * HotSpot SPARC specific backend.
  */
-public class SPARCHotSpotBackend extends HotSpotHostBackend {
+public class SPARCHotSpotBackend extends HotSpotHostBackend implements LIRGenerationProvider {
 
     private static final SizeEstimateStatistics CONSTANT_ESTIMATED_STATS = new SizeEstimateStatistics("ESTIMATE");
     private static final SizeEstimateStatistics CONSTANT_ACTUAL_STATS = new SizeEstimateStatistics("ACTUAL");
@@ -134,15 +135,10 @@
         }
     }
 
-    @Override
-    public FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig) {
+    private FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig) {
         RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig;
-        return new SPARCFrameMapBuilder(newFrameMap(registerConfigNonNull), getCodeCache(), registerConfigNonNull);
-    }
-
-    @Override
-    public FrameMap newFrameMap(RegisterConfig registerConfig) {
-        return new SPARCFrameMap(getCodeCache(), registerConfig, this);
+        FrameMap frameMap = new SPARCFrameMap(getCodeCache(), registerConfigNonNull, this);
+        return new SPARCFrameMapBuilder(frameMap, getCodeCache(), registerConfigNonNull);
     }
 
     @Override
@@ -151,8 +147,9 @@
     }
 
     @Override
-    public LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, FrameMapBuilder frameMapBuilder, StructuredGraph graph, Object stub) {
-        return new HotSpotLIRGenerationResult(compilationId, lir, frameMapBuilder, makeCallingConvention(graph, (Stub) stub), stub, config.requiresReservedStackCheck(graph.getMethods()));
+    public LIRGenerationResult newLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, RegisterConfig registerConfig, StructuredGraph graph, Object stub) {
+        return new HotSpotLIRGenerationResult(compilationId, lir, newFrameMapBuilder(registerConfig), makeCallingConvention(graph, (Stub) stub), stub,
+                        config.requiresReservedStackCheck(graph.getMethods()));
     }
 
     @Override
@@ -227,18 +224,13 @@
     }
 
     @Override
-    protected Assembler createAssembler(FrameMap frameMap) {
-        return new SPARCMacroAssembler(getTarget());
-    }
-
-    @Override
     public CompilationResultBuilder newCompilationResultBuilder(LIRGenerationResult lirGenRes, FrameMap frameMap, CompilationResult compilationResult, CompilationResultBuilderFactory factory) {
         HotSpotLIRGenerationResult gen = (HotSpotLIRGenerationResult) lirGenRes;
         LIR lir = gen.getLIR();
         assert gen.getDeoptimizationRescueSlot() == null || frameMap.frameNeedsAllocating() : "method that can deoptimize must have a frame";
 
         Stub stub = gen.getStub();
-        Assembler masm = createAssembler(frameMap);
+        Assembler masm = new SPARCMacroAssembler(getTarget());
         // On SPARC we always use stack frames.
         HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null);
         DataBuilder dataBuilder = new HotSpotDataBuilder(getCodeCache().getTarget());
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotMove.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotMove.java	Tue Mar 12 19:17:42 2019 +0100
@@ -24,20 +24,21 @@
 
 package org.graalvm.compiler.hotspot.sparc;
 
+import static jdk.vm.ci.code.ValueUtil.asRegister;
 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BPR;
 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Annul.ANNUL;
+import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Annul.NOT_ANNUL;
+import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BranchPredict.PREDICT_NOT_TAKEN;
 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BranchPredict.PREDICT_TAKEN;
+import static org.graalvm.compiler.asm.sparc.SPARCAssembler.RCondition.Rc_nz;
 import static org.graalvm.compiler.asm.sparc.SPARCAssembler.RCondition.Rc_z;
 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL;
 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;
 import static org.graalvm.compiler.lir.sparc.SPARCMove.loadFromConstantTable;
-import static jdk.vm.ci.code.ValueUtil.asRegister;
 
 import org.graalvm.compiler.asm.Label;
 import org.graalvm.compiler.asm.sparc.SPARCAddress;
-import org.graalvm.compiler.asm.sparc.SPARCAssembler.CC;
-import org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag;
 import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler;
 import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler.ScratchRegister;
 import org.graalvm.compiler.core.common.CompressEncoding;
@@ -53,6 +54,7 @@
 import jdk.vm.ci.hotspot.HotSpotConstant;
 import jdk.vm.ci.meta.AllocatableValue;
 import jdk.vm.ci.meta.Constant;
+import jdk.vm.ci.sparc.SPARC;
 
 public class SPARCHotSpotMove {
 
@@ -150,17 +152,33 @@
             if (encoding.hasBase()) {
                 Register baseReg = asRegister(baseRegister);
                 if (!nonNull) {
-                    masm.cmp(inputRegister, baseReg);
-                    masm.movcc(ConditionFlag.Equal, CC.Xcc, baseReg, resReg);
-                    masm.sub(resReg, baseReg, resReg);
+                    Label done = new Label();
+                    if (inputRegister.equals(resReg)) {
+                        BPR.emit(masm, Rc_nz, ANNUL, PREDICT_TAKEN, inputRegister, done);
+                        masm.sub(inputRegister, baseReg, resReg);
+                        masm.bind(done);
+                        if (encoding.getShift() != 0) {
+                            masm.srlx(resReg, encoding.getShift(), resReg);
+                        }
+                    } else {
+                        BPR.emit(masm, Rc_z, NOT_ANNUL, PREDICT_NOT_TAKEN, inputRegister, done);
+                        masm.mov(SPARC.g0, resReg);
+                        masm.sub(inputRegister, baseReg, resReg);
+                        if (encoding.getShift() != 0) {
+                            masm.srlx(resReg, encoding.getShift(), resReg);
+                        }
+                        masm.bind(done);
+                    }
                 } else {
                     masm.sub(inputRegister, baseReg, resReg);
-                }
-                if (encoding.getShift() != 0) {
-                    masm.srlx(resReg, encoding.getShift(), resReg);
+                    if (encoding.getShift() != 0) {
+                        masm.srlx(resReg, encoding.getShift(), resReg);
+                    }
                 }
             } else {
-                masm.srlx(inputRegister, encoding.getShift(), resReg);
+                if (encoding.getShift() != 0) {
+                    masm.srlx(inputRegister, encoding.getShift(), resReg);
+                }
             }
         }
     }
@@ -196,7 +214,7 @@
         public static void emitUncompressCode(SPARCMacroAssembler masm, Register inputRegister, Register resReg, Register baseReg, int shift, boolean nonNull) {
             Register secondaryInput;
             if (shift != 0) {
-                masm.sll(inputRegister, shift, resReg);
+                masm.sllx(inputRegister, shift, resReg);
                 secondaryInput = resReg;
             } else {
                 secondaryInput = inputRegister;
@@ -207,7 +225,7 @@
                     masm.add(secondaryInput, baseReg, resReg);
                 } else {
                     Label done = new Label();
-                    BPR.emit(masm, Rc_z, ANNUL, PREDICT_TAKEN, secondaryInput, done);
+                    BPR.emit(masm, Rc_nz, ANNUL, PREDICT_TAKEN, secondaryInput, done);
                     masm.add(baseReg, secondaryInput, resReg);
                     masm.bind(done);
                 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java	Tue Mar 12 19:17:42 2019 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -47,7 +47,7 @@
 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Binding;
 import org.graalvm.compiler.runtime.RuntimeProvider;
-import org.graalvm.compiler.serviceprovider.GraalServices;
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
 import org.graalvm.compiler.test.GraalTest;
 import org.junit.Test;
 
@@ -257,7 +257,8 @@
                         "java/lang/reflect/Array.newArray(Ljava/lang/Class;I)Ljava/lang/Object;",
                         // HotSpot MacroAssembler-based intrinsic
                         "sun/nio/cs/ISO_8859_1$Encoder.encodeISOArray([CI[BII)I",
-                        // Stub based intrinsics but implementation seems complex in C2
+                        // We have implemented implCompressMultiBlock0 on JDK9+. Does it worth
+                        // backporting as corresponding HotSpot stubs are only generated on SPARC?
                         "sun/security/provider/DigestBase.implCompressMultiBlock([BII)I");
 
         // See JDK-8207146.
@@ -271,18 +272,12 @@
                             "jdk/jfr/internal/JVM.getClassId(Ljava/lang/Class;)J");
 
             add(toBeInvestigated,
-                            // Some logic and a stub call
-                            "com/sun/crypto/provider/CounterMode.implCrypt([BII[BI)I",
-                            // Stub and very little logic
-                            "com/sun/crypto/provider/GHASH.processBlocks([BII[J[J)V",
                             // HotSpot MacroAssembler-based intrinsic
                             "java/lang/Math.fma(DDD)D",
                             // HotSpot MacroAssembler-based intrinsic
                             "java/lang/Math.fma(FFF)F",
                             // Just check if the argument is a compile time constant
                             "java/lang/invoke/MethodHandleImpl.isCompileConstant(Ljava/lang/Object;)Z",
-                            // Some logic and a runtime call
-                            "java/util/ArraysSupport.vectorizedMismatch(Ljava/lang/Object;JLjava/lang/Object;JII)I",
                             // Only used as a marker for vectorization?
                             "java/util/stream/Streams$RangeIntSpliterator.forEachRemaining(Ljava/util/function/IntConsumer;)V",
                             // Only implemented on non-AMD64 platforms (some logic and runtime call)
@@ -295,9 +290,7 @@
                             // Control flow, deopts, and a cast
                             "jdk/internal/util/Preconditions.checkIndex(IILjava/util/function/BiFunction;)I",
                             // HotSpot MacroAssembler-based intrinsic
-                            "sun/nio/cs/ISO_8859_1$Encoder.implEncodeISOArray([CI[BII)I",
-                            // Runtime call and some complex compiler logic
-                            "sun/security/provider/DigestBase.implCompressMultiBlock0([BII)I");
+                            "sun/nio/cs/ISO_8859_1$Encoder.implEncodeISOArray([CI[BII)I");
 
             /*
              * Per default, all these operations are mapped to some generic method for which we
@@ -344,27 +337,45 @@
             // Compact string support - HotSpot MacroAssembler-based intrinsic or complex C2 logic.
             add(toBeInvestigated,
                             "java/lang/StringCoding.hasNegatives([BII)Z",
-                            "java/lang/StringCoding.implEncodeISOArray([BI[BII)I",
+                            "java/lang/StringCoding.implEncodeISOArray([BI[BII)I");
+            add(ignore,
+                            // handled through an intrinsic for String.equals itself
+                            "java/lang/StringLatin1.equals([B[B)Z",
+
+                            // handled by an intrinsic for StringLatin1.indexOf([BI[BII)I
                             "java/lang/StringLatin1.indexOf([B[B)I",
-                            "java/lang/StringUTF16.getChar([BI)C",
-                            "java/lang/StringUTF16.getChars([BII[CI)V",
+
+                            // handled through an intrinsic for String.equals itself
+                            "java/lang/StringUTF16.equals([B[B)Z",
+
+                            // handled by an intrinsic for StringUTF16.indexOfUnsafe
                             "java/lang/StringUTF16.indexOf([BI[BII)I",
                             "java/lang/StringUTF16.indexOf([B[B)I",
+
+                            // handled by an intrinsic for StringUTF16.indexOfCharUnsafe
                             "java/lang/StringUTF16.indexOfChar([BIII)I",
+
+                            // handled by an intrinsic for StringUTF16.indexOfLatin1Unsafe
                             "java/lang/StringUTF16.indexOfLatin1([BI[BII)I",
-                            "java/lang/StringUTF16.indexOfLatin1([B[B)I",
-                            "java/lang/StringUTF16.putChar([BII)V",
-                            "java/lang/StringUTF16.toBytes([CII)[B");
-            // These are handled through an intrinsic for String.equals itself
-            add(ignore,
-                            "java/lang/StringLatin1.equals([B[B)Z",
-                            "java/lang/StringUTF16.equals([B[B)Z");
+                            "java/lang/StringUTF16.indexOfLatin1([B[B)I");
+
+            if (!config.useAESCTRIntrinsics) {
+                add(ignore,
+                                "com/sun/crypto/provider/CounterMode.implCrypt([BII[BI)I");
+            }
+            if (!config.useGHASHIntrinsics()) {
+                add(ignore,
+                                "com/sun/crypto/provider/GHASH.processBlocks([BII[J[J)V");
+            }
+            if (!(config.useSHA1Intrinsics() || config.useSHA256Intrinsics() || config.useSHA512Intrinsics())) {
+                add(ignore,
+                                "sun/security/provider/DigestBase.implCompressMultiBlock0([BII)I");
+            }
         }
 
         if (isJDK10OrHigher()) {
             add(toBeInvestigated,
-                            "java/lang/Math.multiplyHigh(JJ)J",
-                            "jdk/internal/util/ArraysSupport.vectorizedMismatch(Ljava/lang/Object;JLjava/lang/Object;JII)I");
+                            "java/lang/Math.multiplyHigh(JJ)J");
         }
 
         if (isJDK11OrHigher()) {
@@ -401,10 +412,16 @@
             // Can we implement these on non-AMD64 platforms? C2 seems to.
             add(toBeInvestigated,
                             "java/lang/String.compareTo(Ljava/lang/String;)I",
+                            "java/lang/StringLatin1.indexOf([B[B)I",
                             "java/lang/StringLatin1.inflate([BI[BII)V",
                             "java/lang/StringLatin1.inflate([BI[CII)V",
                             "java/lang/StringUTF16.compress([BI[BII)I",
                             "java/lang/StringUTF16.compress([CI[BII)I",
+                            "java/lang/StringUTF16.indexOf([BI[BII)I",
+                            "java/lang/StringUTF16.indexOf([B[B)I",
+                            "java/lang/StringUTF16.indexOfChar([BIII)I",
+                            "java/lang/StringUTF16.indexOfLatin1([BI[BII)I",
+                            "java/lang/StringUTF16.indexOfLatin1([B[B)I",
                             "jdk/internal/misc/Unsafe.compareAndExchangeByte(Ljava/lang/Object;JBB)B",
                             "jdk/internal/misc/Unsafe.compareAndExchangeShort(Ljava/lang/Object;JSS)S",
                             "jdk/internal/misc/Unsafe.compareAndSetByte(Ljava/lang/Object;JBB)Z",
@@ -433,7 +450,9 @@
                                     "jdk/internal/misc/Unsafe.getAndSet" + oopName + "(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;");
                 }
                 add(toBeInvestigated,
+                                "com/sun/crypto/provider/CounterMode.implCrypt([BII[BI)I",
                                 "java/lang/Thread.onSpinWait()V",
+                                "java/util/ArraysSupport.vectorizedMismatch(Ljava/lang/Object;JLjava/lang/Object;JII)I",
                                 "jdk/internal/misc/Unsafe.getCharUnaligned(Ljava/lang/Object;J)C",
                                 "jdk/internal/misc/Unsafe.getIntUnaligned(Ljava/lang/Object;J)I",
                                 "jdk/internal/misc/Unsafe.getLongUnaligned(Ljava/lang/Object;J)J",
@@ -443,6 +462,10 @@
                                 "jdk/internal/misc/Unsafe.putLongUnaligned(Ljava/lang/Object;JJ)V",
                                 "jdk/internal/misc/Unsafe.putShortUnaligned(Ljava/lang/Object;JS)V");
             }
+            if (isJDK10OrHigher()) {
+                add(toBeInvestigated,
+                                "jdk/internal/util/ArraysSupport.vectorizedMismatch(Ljava/lang/Object;JLjava/lang/Object;JII)I");
+            }
         }
 
         /*
@@ -535,23 +558,23 @@
     }
 
     private static boolean isJDK9OrHigher() {
-        return GraalServices.JAVA_SPECIFICATION_VERSION >= 9;
+        return JavaVersionUtil.JAVA_SPECIFICATION_VERSION >= 9;
     }
 
     private static boolean isJDK10OrHigher() {
-        return GraalServices.JAVA_SPECIFICATION_VERSION >= 10;
+        return JavaVersionUtil.JAVA_SPECIFICATION_VERSION >= 10;
     }
 
     private static boolean isJDK11OrHigher() {
-        return GraalServices.JAVA_SPECIFICATION_VERSION >= 11;
+        return JavaVersionUtil.JAVA_SPECIFICATION_VERSION >= 11;
     }
 
     private static boolean isJDK12OrHigher() {
-        return GraalServices.JAVA_SPECIFICATION_VERSION >= 12;
+        return JavaVersionUtil.JAVA_SPECIFICATION_VERSION >= 12;
     }
 
     private static boolean isJDK13OrHigher() {
-        return GraalServices.JAVA_SPECIFICATION_VERSION >= 13;
+        return JavaVersionUtil.JAVA_SPECIFICATION_VERSION >= 13;
     }
 
     public interface Refiner {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java	Tue Mar 12 19:17:42 2019 +0100
@@ -31,7 +31,7 @@
 import static org.graalvm.compiler.core.test.ReflectionOptionDescriptors.extractEntries;
 import static org.graalvm.compiler.debug.MemUseTrackerKey.getCurrentThreadAllocatedBytes;
 import static org.graalvm.compiler.hotspot.test.CompileTheWorld.Options.DESCRIPTORS;
-import static org.graalvm.compiler.serviceprovider.GraalServices.Java8OrEarlier;
+import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.Java8OrEarlier;
 
 import java.io.Closeable;
 import java.io.File;
@@ -90,7 +90,7 @@
 import org.graalvm.compiler.options.OptionKey;
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.options.OptionsParser;
-import org.graalvm.compiler.serviceprovider.GraalServices;
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
 
 import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider;
 import jdk.vm.ci.hotspot.HotSpotCompilationRequest;
@@ -110,7 +110,7 @@
 
     /**
      * Magic token to denote that JDK classes are to be compiled. If
-     * {@link GraalServices#Java8OrEarlier}, then the classes in {@code rt.jar} are compiled.
+     * {@link JavaVersionUtil#Java8OrEarlier}, then the classes in {@code rt.jar} are compiled.
      * Otherwise the classes in the Java runtime image are compiled.
      */
     public static final String SUN_BOOT_CLASS_PATH = "sun.boot.class.path";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/EliminateRedundantInitializationPhaseTest.java	Tue Mar 12 19:17:42 2019 +0100
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 org.graalvm.compiler.hotspot.test;
+
+import org.graalvm.compiler.core.test.GraalCompilerTest;
+import org.graalvm.compiler.hotspot.meta.HotSpotClassInitializationPlugin;
+import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode;
+import org.graalvm.compiler.hotspot.phases.aot.EliminateRedundantInitializationPhase;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
+import org.graalvm.compiler.phases.tiers.HighTierContext;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class EliminateRedundantInitializationPhaseTest extends GraalCompilerTest {
+    @Override
+    protected Plugins getDefaultGraphBuilderPlugins() {
+        Plugins plugins = super.getDefaultGraphBuilderPlugins();
+        plugins.setClassInitializationPlugin(new HotSpotClassInitializationPlugin());
+        return plugins;
+    }
+
+    public static class X {
+        public static int x;
+        public static int y;
+        public static int z;
+    }
+
+    public static class Y extends X {
+        public static int a;
+        public static int b;
+    }
+
+    public static void assignFields() {
+        X.x = 1;
+        X.y = 2;
+        X.z = 3;
+    }
+
+    public static void assignFieldsConditionally(boolean choice) {
+        X.x = 1;
+        if (choice) {
+            X.y = 2;
+        } else {
+            X.z = 3;
+        }
+    }
+
+    public static void assignFieldsSubclassDominates() {
+        Y.a = 1;
+        X.x = 2;
+        X.y = 3;
+        X.z = 4;
+    }
+
+    public static void assignFieldsConditionallySubclassDominates(boolean choice) {
+        Y.a = 1;
+        if (choice) {
+            X.x = 2;
+        } else {
+            X.y = 3;
+        }
+        Y.z = 4;
+    }
+
+    public static void assignFieldsSubclassPostdominates() {
+        X.x = 1;
+        Y.a = 2;
+    }
+
+    public static void assignFieldsConditionallySubclassPostdominates(boolean choice) {
+        X.x = 1;
+        if (choice) {
+            X.y = 2;
+        } else {
+            X.z = 3;
+        }
+        Y.a = 4;
+    }
+
+    public static void assignFieldsConditionallyMixed(boolean choice) {
+        X.x = 1;
+        if (choice) {
+            Y.a = 2;
+        } else {
+            X.z = 3;
+        }
+        Y.b = 4;
+    }
+
+    public static void assignFieldsInLoop() {
+        X.x = 1;
+        for (int i = 0; i < 10; i++) {
+            X.y += X.z;
+        }
+    }
+
+    public static void assignFieldsInBranches(boolean choice) {
+        if (choice) {
+            X.x = 1;
+        } else {
+            X.y = 2;
+        }
+        X.z = 3;
+    }
+
+    public static void assignFieldsInBranchesMixed(boolean choice) {
+        if (choice) {
+            X.x = 1;
+        } else {
+            Y.a = 2;
+        }
+        X.z = 3;
+    }
+
+    static class SomeClass {
+        @BytecodeParserNeverInline
+        static void method() {
+        }
+
+        @BytecodeParserForceInline
+        static void inlinedMethod() {
+        }
+    }
+
+    public static void invokestatic() {
+        SomeClass.method();
+    }
+
+    public static void invokestaticInlined() {
+        SomeClass.inlinedMethod();
+    }
+
+    private void test(String name, int initNodesAfterParse, int initNodesAfterOpt) {
+        StructuredGraph graph = parseEager(name, AllowAssumptions.NO);
+        Assert.assertEquals(initNodesAfterParse, graph.getNodes().filter(InitializeKlassNode.class).count());
+        HighTierContext highTierContext = getDefaultHighTierContext();
+        new EliminateRedundantInitializationPhase().apply(graph, highTierContext);
+        Assert.assertEquals(initNodesAfterOpt, graph.getNodes().filter(InitializeKlassNode.class).count());
+    }
+
+    @Test
+    public void test1() {
+        test("assignFields", 3, 1);
+    }
+
+    @Test
+    public void test2() {
+        test("assignFieldsConditionally", 3, 1);
+    }
+
+    @Test
+    public void test3() {
+        test("assignFieldsSubclassDominates", 4, 1);
+    }
+
+    @Test
+    public void test4() {
+        test("assignFieldsConditionallySubclassDominates", 4, 1);
+    }
+
+    @Test
+    public void test5() {
+        test("assignFieldsSubclassPostdominates", 2, 2);
+    }
+
+    @Test
+    public void test6() {
+        test("assignFieldsConditionallySubclassPostdominates", 4, 2);
+    }
+
+    @Test
+    public void test7() {
+        test("assignFieldsConditionallyMixed", 4, 3);
+    }
+
+    @Test
+    public void test8() {
+        test("assignFieldsInLoop", 4, 1);
+    }
+
+    @Test
+    public void test9() {
+        test("assignFieldsInBranches", 3, 2);
+    }
+
+    @Test
+    public void test10() {
+        test("assignFieldsInBranchesMixed", 3, 2);
+    }
+
+    @Test
+    public void test11() {
+        test("invokestatic", 1, 0);
+    }
+
+    @Test
+    public void test12() {
+        test("invokestaticInlined", 1, 1);
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTest.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTest.java	Tue Mar 12 19:17:42 2019 +0100
@@ -53,6 +53,11 @@
         testOSR(getInitialOptions(), "testNonReduceLoop");
     }
 
+    @Test
+    public void testOSR04() {
+        testOSR(getInitialOptions(), "testDeoptAfterCountedLoop");
+    }
+
     static int limit = 10000;
 
     public static int sideEffect;
@@ -100,4 +105,14 @@
         GraalDirectives.controlFlowAnchor();
         return ret;
     }
+
+    public static ReturnValue testDeoptAfterCountedLoop() {
+        long ret = 0;
+        for (int i = 0; GraalDirectives.injectBranchProbability(1, i < limit * limit); i++) {
+            GraalDirectives.blackhole(i);
+            ret = GraalDirectives.opaque(i);
+        }
+        GraalDirectives.controlFlowAnchor();
+        return ret + 1 == limit * limit ? ReturnValue.SUCCESS : ReturnValue.FAILURE;
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/JVMCIInfopointErrorTest.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/JVMCIInfopointErrorTest.java	Tue Mar 12 19:17:42 2019 +0100
@@ -24,6 +24,7 @@
 
 package org.graalvm.compiler.hotspot.test;
 
+import static org.graalvm.compiler.debug.DebugOptions.DumpOnError;
 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;
 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED;
@@ -52,6 +53,7 @@
 import org.graalvm.compiler.nodes.StructuredGraph;
 import org.graalvm.compiler.nodes.spi.LIRLowerable;
 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
+import org.graalvm.compiler.options.OptionValues;
 import org.junit.Test;
 
 import jdk.vm.ci.code.BytecodeFrame;
@@ -139,6 +141,14 @@
         test(getDebugContext(), spec);
     }
 
+    /**
+     * Avoids dumping during tests which are expected to fail.
+     */
+    private void testNoDump(TestSpec spec) {
+        OptionValues options = new OptionValues(getInitialOptions(), DumpOnError, false);
+        test(getDebugContext(options, null, null), spec);
+    }
+
     private void test(DebugContext debug, TestSpec spec) {
         ResolvedJavaMethod method = getResolvedJavaMethod("testMethod");
 
@@ -154,7 +164,7 @@
 
     @Test(expected = Error.class)
     public void testInvalidShortOop() {
-        test((tool, state, safepoint) -> {
+        testNoDump((tool, state, safepoint) -> {
             PlatformKind kind = tool.target().arch.getPlatformKind(JavaKind.Short);
             LIRKind lirKind = LIRKind.reference(kind);
 
@@ -167,7 +177,7 @@
 
     @Test(expected = Error.class)
     public void testInvalidShortDerivedOop() {
-        test((tool, state, safepoint) -> {
+        testNoDump((tool, state, safepoint) -> {
             Variable baseOop = tool.newVariable(LIRKind.fromJavaKind(tool.target().arch, JavaKind.Object));
             tool.append(new ValueDef(baseOop));
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/OptionsInFileTest.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/OptionsInFileTest.java	Tue Mar 12 19:17:42 2019 +0100
@@ -37,6 +37,7 @@
 import java.util.List;
 
 import org.graalvm.compiler.core.test.GraalCompilerTest;
+import org.graalvm.compiler.debug.DebugOptions.PrintGraphTarget;
 import org.graalvm.compiler.test.SubprocessUtil;
 import org.graalvm.compiler.test.SubprocessUtil.Subprocess;
 import org.junit.Assert;
@@ -54,12 +55,12 @@
         try {
             Assert.assertFalse(methodFilterValue.equals(MethodFilter.getDefaultValue()));
             Assert.assertFalse(debugFilterValue.equals(Dump.getDefaultValue()));
-            Assert.assertTrue(PrintGraph.getDefaultValue());
+            Assert.assertEquals(PrintGraphTarget.File, PrintGraph.getDefaultValue());
 
             try (PrintStream out = new PrintStream(new FileOutputStream(optionsFile))) {
                 out.println(MethodFilter.getName() + "=" + methodFilterValue);
                 out.println(Dump.getName() + "=" + debugFilterValue);
-                out.println(PrintGraph.getName() + " = false");
+                out.println(PrintGraph.getName() + " = Network");
             }
 
             List<String> vmArgs = withoutDebuggerArguments(getVMCommandLine());
@@ -70,7 +71,7 @@
             String[] expected = {
                             "graal.MethodFilter := \"a very unlikely method name\"",
                             "graal.Dump := \"a very unlikely debug scope\"",
-                            "graal.PrintGraph := false"};
+                            "graal.PrintGraph := Network"};
             for (String line : proc.output) {
                 for (int i = 0; i < expected.length; i++) {
                     if (expected[i] != null && line.contains(expected[i])) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ReservedStackAccessTest.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ReservedStackAccessTest.java	Tue Mar 12 19:17:42 2019 +0100
@@ -73,6 +73,10 @@
         vmArgs.add("-XX:+UseJVMCICompiler");
         vmArgs.add("-Dgraal.Inline=false");
         vmArgs.add("-XX:CompileCommand=exclude,java/util/concurrent/locks/AbstractOwnableSynchronizer.setExclusiveOwnerThread");
+
+        // Avoid SOE in HotSpotJVMCIRuntime.adjustCompilationLevel
+        vmArgs.add("-Dgraal.CompileGraalWithC1Only=false");
+
         Subprocess proc = SubprocessUtil.java(vmArgs, ReservedStackAccessTest.class.getName());
         boolean passed = false;
         for (String line : proc.output) {
@@ -81,9 +85,7 @@
             }
         }
         if (!passed) {
-            for (String line : proc.output) {
-                System.err.println("" + line);
-            }
+            System.err.println(proc);
         }
         assertTrue(passed);
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierAdditionTest.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierAdditionTest.java	Tue Mar 12 19:17:42 2019 +0100
@@ -32,10 +32,10 @@
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase;
-import org.graalvm.compiler.hotspot.nodes.G1PostWriteBarrier;
-import org.graalvm.compiler.hotspot.nodes.G1PreWriteBarrier;
-import org.graalvm.compiler.hotspot.nodes.G1ReferentFieldReadBarrier;
-import org.graalvm.compiler.hotspot.nodes.SerialWriteBarrier;
+import org.graalvm.compiler.hotspot.gc.g1.G1PostWriteBarrier;
+import org.graalvm.compiler.hotspot.gc.g1.G1PreWriteBarrier;
+import org.graalvm.compiler.hotspot.gc.g1.G1ReferentFieldReadBarrier;
+import org.graalvm.compiler.hotspot.gc.shared.SerialWriteBarrier;
 import org.graalvm.compiler.hotspot.phases.WriteBarrierAdditionPhase;
 import org.graalvm.compiler.nodes.StructuredGraph;
 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierVerificationTest.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierVerificationTest.java	Tue Mar 12 19:17:42 2019 +0100
@@ -32,12 +32,12 @@
 import org.graalvm.compiler.debug.DebugContext.Scope;
 import org.graalvm.compiler.debug.DebugDumpScope;
 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
-import org.graalvm.compiler.hotspot.nodes.G1ArrayRangePostWriteBarrier;
-import org.graalvm.compiler.hotspot.nodes.G1ArrayRangePreWriteBarrier;
-import org.graalvm.compiler.hotspot.nodes.G1PostWriteBarrier;
-import org.graalvm.compiler.hotspot.nodes.G1PreWriteBarrier;
-import org.graalvm.compiler.hotspot.nodes.SerialArrayRangeWriteBarrier;
-import org.graalvm.compiler.hotspot.nodes.SerialWriteBarrier;
+import org.graalvm.compiler.hotspot.gc.g1.G1ArrayRangePostWriteBarrier;
+import org.graalvm.compiler.hotspot.gc.g1.G1ArrayRangePreWriteBarrier;
+import org.graalvm.compiler.hotspot.gc.g1.G1PostWriteBarrier;
+import org.graalvm.compiler.hotspot.gc.g1.G1PreWriteBarrier;
+import org.graalvm.compiler.hotspot.gc.shared.SerialArrayRangeWriteBarrier;
+import org.graalvm.compiler.hotspot.gc.shared.SerialWriteBarrier;
 import org.graalvm.compiler.hotspot.phases.WriteBarrierAdditionPhase;
 import org.graalvm.compiler.hotspot.phases.WriteBarrierVerificationPhase;
 import org.graalvm.compiler.nodes.AbstractBeginNode;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java	Tue Mar 12 19:17:42 2019 +0100
@@ -368,8 +368,14 @@
         installedCode = null;
         Object[] context = {new DebugDumpScope(getIdString(), true), codeCache, getMethod(), compResult};
         try (DebugContext.Scope s = debug.scope("CodeInstall", context)) {
-            installedCode = (HotSpotInstalledCode) backend.createInstalledCode(debug, getRequest().getMethod(), getRequest(), compResult,
-                            getRequest().getMethod().getSpeculationLog(), null, installAsDefault, context);
+            HotSpotCompilationRequest request = getRequest();
+            installedCode = (HotSpotInstalledCode) backend.createInstalledCode(debug,
+                            request.getMethod(),
+                            request,
+                            compResult,
+                            null,
+                            installAsDefault,
+                            context);
         } catch (Throwable e) {
             throw debug.handle(e);
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java	Tue Mar 12 19:17:42 2019 +0100
@@ -92,6 +92,7 @@
     public final boolean useBiasedLocking = getFlag("UseBiasedLocking", Boolean.class);
     public final boolean usePopCountInstruction = getFlag("UsePopCountInstruction", Boolean.class);
     public final boolean useAESIntrinsics = getFlag("UseAESIntrinsics", Boolean.class);
+    public final boolean useAESCTRIntrinsics = getFlag("UseAESCTRIntrinsics", Boolean.class, false);
     public final boolean useCRC32Intrinsics = getFlag("UseCRC32Intrinsics", Boolean.class);
     public final boolean useCRC32CIntrinsics = versioned.useCRC32CIntrinsics;
     public final boolean threadLocalHandshakes = getFlag("ThreadLocalHandshakes", Boolean.class, false);
@@ -100,10 +101,12 @@
     private final boolean useSHA1Intrinsics = getFlag("UseSHA1Intrinsics", Boolean.class);
     private final boolean useSHA256Intrinsics = getFlag("UseSHA256Intrinsics", Boolean.class);
     private final boolean useSHA512Intrinsics = getFlag("UseSHA512Intrinsics", Boolean.class);
+    private final boolean useGHASHIntrinsics = getFlag("UseGHASHIntrinsics", Boolean.class, false);
     private final boolean useMontgomeryMultiplyIntrinsic = getFlag("UseMontgomeryMultiplyIntrinsic", Boolean.class, false);
     private final boolean useMontgomerySquareIntrinsic = getFlag("UseMontgomerySquareIntrinsic", Boolean.class, false);
     private final boolean useMulAddIntrinsic = getFlag("UseMulAddIntrinsic", Boolean.class, false);
     private final boolean useSquareToLenIntrinsic = getFlag("UseSquareToLenIntrinsic", Boolean.class, false);
+    public final boolean useVectorizedMismatchIntrinsic = getFlag("UseVectorizedMismatchIntrinsic", Boolean.class, false);
 
     /*
      * These are methods because in some JDKs the flags are visible but the stubs themselves haven't
@@ -114,15 +117,19 @@
     }
 
     public boolean useSHA1Intrinsics() {
-        return useSHA1Intrinsics && sha1ImplCompress != 0;
+        return useSHA1Intrinsics && sha1ImplCompress != 0 && sha1ImplCompressMultiBlock != 0;
     }
 
     public boolean useSHA256Intrinsics() {
-        return useSHA256Intrinsics && sha256ImplCompress != 0;
+        return useSHA256Intrinsics && sha256ImplCompress != 0 && sha256ImplCompressMultiBlock != 0;
     }
 
     public boolean useSHA512Intrinsics() {
-        return useSHA512Intrinsics && sha512ImplCompress != 0;
+        return useSHA512Intrinsics && sha512ImplCompress != 0 && sha512ImplCompressMultiBlock != 0;
+    }
+
+    public boolean useGHASHIntrinsics() {
+        return useGHASHIntrinsics && ghashProcessBlocks != 0;
     }
 
     public boolean useMontgomeryMultiplyIntrinsic() {
@@ -309,7 +316,17 @@
     public final int jvmAccWrittenFlags = getConstant("JVM_ACC_WRITTEN_FLAGS", Integer.class);
     public final int jvmAccSynthetic = getConstant("JVM_ACC_SYNTHETIC", Integer.class);
 
-    public final int jvmciCompileStateCanPostOnExceptionsOffset = getFieldOffset("JVMCIEnv::_jvmti_can_post_on_exceptions", Integer.class, "jbyte", Integer.MIN_VALUE);
+    public final int jvmciCompileStateCanPostOnExceptionsOffset = getJvmciCompileStateCanPostOnExceptionsOffset();
+
+    // Integer.MIN_VALUE if not available
+    private int getJvmciCompileStateCanPostOnExceptionsOffset() {
+        int offset = getFieldOffset("JVMCICompileState::_jvmti_can_post_on_exceptions", Integer.class, "jbyte", Integer.MIN_VALUE);
+        if (offset == Integer.MIN_VALUE) {
+            // JDK 12
+            offset = getFieldOffset("JVMCIEnv::_jvmti_can_post_on_exceptions", Integer.class, "jbyte", Integer.MIN_VALUE);
+        }
+        return offset;
+    }
 
     public final int threadTlabOffset = getFieldOffset("Thread::_tlab", Integer.class, "ThreadLocalAllocBuffer");
     public final int javaThreadAnchorOffset = getFieldOffset("JavaThread::_anchor", Integer.class, "JavaFrameAnchor");
@@ -372,12 +389,29 @@
     public final int pendingExceptionOffset = getFieldOffset("ThreadShadow::_pending_exception", Integer.class, "oop");
 
     public final int pendingDeoptimizationOffset = getFieldOffset("JavaThread::_pending_deoptimization", Integer.class, "int");
-    public final int pendingFailedSpeculationOffset = getFieldOffset("JavaThread::_pending_failed_speculation", Integer.class, "long");
     public final int pendingTransferToInterpreterOffset = getFieldOffset("JavaThread::_pending_transfer_to_interpreter", Integer.class, "bool");
 
     private final int javaFrameAnchorLastJavaSpOffset = getFieldOffset("JavaFrameAnchor::_last_Java_sp", Integer.class, "intptr_t*");
     private final int javaFrameAnchorLastJavaPcOffset = getFieldOffset("JavaFrameAnchor::_last_Java_pc", Integer.class, "address");
 
+    public final int pendingFailedSpeculationOffset;
+    {
+        String name = "JavaThread::_pending_failed_speculation";
+        int offset = -1;
+        try {
+            offset = getFieldOffset(name, Integer.class, "jlong");
+        } catch (JVMCIError e) {
+            try {
+                offset = getFieldOffset(name, Integer.class, "long");
+            } catch (JVMCIError e2) {
+            }
+        }
+        if (offset == -1) {
+            throw new JVMCIError("cannot get offset of field " + name + " with type long or jlong");
+        }
+        pendingFailedSpeculationOffset = offset;
+    }
+
     public int threadLastJavaSpOffset() {
         return javaThreadAnchorOffset + javaFrameAnchorLastJavaSpOffset;
     }
@@ -602,11 +636,11 @@
     public final long crcTableAddress = getFieldValue("StubRoutines::_crc_table_adr", Long.class, "address");
 
     public final long sha1ImplCompress = getFieldValue("StubRoutines::_sha1_implCompress", Long.class, "address", 0L);
-    public final long sha1ImplCompressMB = getFieldValue("StubRoutines::_sha1_implCompressMB", Long.class, "address", 0L);
+    public final long sha1ImplCompressMultiBlock = getFieldValue("StubRoutines::_sha1_implCompressMB", Long.class, "address", 0L);
     public final long sha256ImplCompress = getFieldValue("StubRoutines::_sha256_implCompress", Long.class, "address", 0L);
-    public final long sha256ImplCompressMB = getFieldValue("StubRoutines::_sha256_implCompressMB", Long.class, "address", 0L);
+    public final long sha256ImplCompressMultiBlock = getFieldValue("StubRoutines::_sha256_implCompressMB", Long.class, "address", 0L);
     public final long sha512ImplCompress = getFieldValue("StubRoutines::_sha512_implCompress", Long.class, "address", 0L);
-    public final long sha512ImplCompressMB = getFieldValue("StubRoutines::_sha512_implCompressMB", Long.class, "address", 0L);
+    public final long sha512ImplCompressMultiBlock = getFieldValue("StubRoutines::_sha512_implCompressMB", Long.class, "address", 0L);
     public final long multiplyToLen = getFieldValue("StubRoutines::_multiplyToLen", Long.class, "address", longRequiredOnAMD64);
 
     public final long counterModeAESCrypt = getFieldValue("StubRoutines::_counterMode_AESCrypt", Long.class, "address", 0L);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java	Tue Mar 12 19:17:42 2019 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -46,6 +46,7 @@
 import org.graalvm.compiler.hotspot.replacements.AESCryptSubstitutions;
 import org.graalvm.compiler.hotspot.replacements.BigIntegerSubstitutions;
 import org.graalvm.compiler.hotspot.replacements.CipherBlockChainingSubstitutions;
+import org.graalvm.compiler.hotspot.replacements.DigestBaseSubstitutions;
 import org.graalvm.compiler.hotspot.replacements.SHA2Substitutions;
 import org.graalvm.compiler.hotspot.replacements.SHA5Substitutions;
 import org.graalvm.compiler.hotspot.replacements.SHASubstitutions;
@@ -71,6 +72,7 @@
 import org.graalvm.compiler.options.OptionType;
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.phases.tiers.SuitesProvider;
+import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
 import org.graalvm.compiler.word.Word;
 import jdk.internal.vm.compiler.word.Pointer;
 
@@ -95,7 +97,7 @@
     public static class Options {
         // @formatter:off
         @Option(help = "Use Graal arithmetic stubs instead of HotSpot stubs where possible")
-        public static final OptionKey<Boolean> GraalArithmeticStubs = new OptionKey<>(false); // GR-8276
+        public static final OptionKey<Boolean> GraalArithmeticStubs = new OptionKey<>(JavaVersionUtil.JAVA_SPECIFICATION_VERSION >= 9);
         @Option(help = "Enables instruction profiling on assembler level. Valid values are a comma separated list of supported instructions." +
                         " Compare with subclasses of Assembler.InstructionCounter.", type = OptionType.Debug)
         public static final OptionKey<String> ASMInstructionProfiling = new OptionKey<>(null);
@@ -261,6 +263,36 @@
     @NodeIntrinsic(ForeignCallNode.class)
     private static native void sha5ImplCompressStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word bufAddr, Object state);
 
+    /**
+     * @see DigestBaseSubstitutions#implCompressMultiBlock0
+     */
+    public static final ForeignCallDescriptor SHA_IMPL_COMPRESS_MB = new ForeignCallDescriptor("shaImplCompressMB", int.class, Word.class, Object.class, int.class, int.class);
+
+    public static int shaImplCompressMBStub(Word bufAddr, Object stateAddr, int ofs, int limit) {
+        return shaImplCompressMBStub(HotSpotBackend.SHA_IMPL_COMPRESS_MB, bufAddr, stateAddr, ofs, limit);
+    }
+
+    @NodeIntrinsic(ForeignCallNode.class)
+    private static native int shaImplCompressMBStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word bufAddr, Object state, int ofs, int limit);
+
+    public static final ForeignCallDescriptor SHA2_IMPL_COMPRESS_MB = new ForeignCallDescriptor("sha2ImplCompressMB", int.class, Word.class, Object.class, int.class, int.class);
+
+    public static int sha2ImplCompressMBStub(Word bufAddr, Object stateAddr, int ofs, int limit) {
+        return sha2ImplCompressMBStub(HotSpotBackend.SHA2_IMPL_COMPRESS_MB, bufAddr, stateAddr, ofs, limit);
+    }
+
+    @NodeIntrinsic(ForeignCallNode.class)
+    private static native int sha2ImplCompressMBStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word bufAddr, Object state, int ofs, int limit);
+
+    public static final ForeignCallDescriptor SHA5_IMPL_COMPRESS_MB = new ForeignCallDescriptor("sha5ImplCompressMB", int.class, Word.class, Object.class, int.class, int.class);
+
+    public static int sha5ImplCompressMBStub(Word bufAddr, Object stateAddr, int ofs, int limit) {
+        return sha5ImplCompressMBStub(HotSpotBackend.SHA5_IMPL_COMPRESS_MB, bufAddr, stateAddr, ofs, limit);
+    }
+
+    @NodeIntrinsic(ForeignCallNode.class)
+    private static native int sha5ImplCompressMBStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word bufAddr, Object state, int ofs, int limit);
+
     public static void unsafeArraycopy(Word srcAddr, Word dstAddr, Word size) {
         unsafeArraycopyStub(UNSAFE_ARRAYCOPY, srcAddr, dstAddr, size);
     }
@@ -269,6 +301,37 @@
     private static native void unsafeArraycopyStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word srcAddr, Word dstAddr, Word size);
 
     /**
+     * Descriptor for {@code StubRoutines::_ghash_processBlocks}.
+     */
+    public static final ForeignCallDescriptor GHASH_PROCESS_BLOCKS = new ForeignCallDescriptor("ghashProcessBlocks", void.class, Word.class, Word.class, Word.class, int.class);
+
+    /**
+     * Descriptor for {@code StubRoutines::_counterMode_AESCrypt}.
+     */
+    public static final ForeignCallDescriptor COUNTERMODE_IMPL_CRYPT = new ForeignCallDescriptor("counterModeAESCrypt", int.class, Word.class, Word.class, Word.class, Word.class, int.class,
+                    Word.class, Word.class);
+
+    public static int counterModeAESCrypt(Word srcAddr, Word dstAddr, Word kPtr, Word cntPtr, int len, Word encCntPtr, Word used) {
+        return counterModeAESCrypt(COUNTERMODE_IMPL_CRYPT, srcAddr, dstAddr, kPtr, cntPtr, len, encCntPtr, used);
+    }
+
+    @NodeIntrinsic(ForeignCallNode.class)
+    private static native int counterModeAESCrypt(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word srcAddr, Word dstAddr, Word kPtr, Word cntPtr, int len, Word encCntPtr,
+                    Word used);
+
+    /**
+     * Descriptor for {@code StubRoutines::_vectorizedMismatch}.
+     */
+    public static final ForeignCallDescriptor VECTORIZED_MISMATCHED = new ForeignCallDescriptor("vectorizedMismatch", int.class, Word.class, Word.class, int.class, int.class);
+
+    public static int vectorizedMismatch(Word aAddr, Word bAddr, int length, int log2ArrayIndexScale) {
+        return vectorizedMismatchStub(VECTORIZED_MISMATCHED, aAddr, bAddr, length, log2ArrayIndexScale);
+    }
+
+    @NodeIntrinsic(ForeignCallNode.class)
+    private static native int vectorizedMismatchStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Word aAddr, Word bAddr, int length, int log2ArrayIndexScale);
+
+    /**
      * @see VMErrorNode
      */
     public static final ForeignCallDescriptor VM_ERROR = new ForeignCallDescriptor("vm_error", void.class, Object.class, Object.class, long.class);
@@ -389,6 +452,13 @@
     }
 
     /**
+     * Translates a set of registers from the callee's perspective to the caller's perspective. This
+     * is needed for architectures where input/output registers are renamed during a call (e.g.
+     * register windows on SPARC). Registers which are not visible by the caller are removed.
+     */
+    protected abstract EconomicSet<Register> translateToCallerRegisters(EconomicSet<Register> calleeRegisters);
+
+    /**
      * Updates a given stub with respect to the registers it destroys.
      * <p>
      * Any entry in {@code calleeSaveInfo} that {@linkplain SaveRegistersOp#supportsRemove()
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java	Tue Mar 12 19:17:42 2019 +0100
@@ -88,7 +88,7 @@
 
         ResolvedJavaMethod[] methods = compResult.getMethods();
 
-        List<CodeAnnotation> annotations = compResult.getAnnotations();
+        List<CodeAnnotation> annotations = compResult.getCodeAnnotations();
         Comment[] comments = new Comment[annotations.size()];
         if (!annotations.isEmpty()) {
             for (int i = 0; i < comments.length; i++) {
@@ -129,16 +129,16 @@
             boolean hasUnsafeAccess = compResult.hasUnsafeAccess();
 
             int id;
-            long jvmciEnv;
+            long jvmciCompileState;
             if (compRequest != null) {
                 id = compRequest.getId();
-                jvmciEnv = compRequest.getJvmciEnv();
+                jvmciCompileState = compRequest.getJvmciEnv();
             } else {
                 id = hsMethod.allocateCompileId(entryBCI);
-                jvmciEnv = 0L;
+                jvmciCompileState = 0L;
             }
             return new HotSpotCompiledNmethod(name, targetCode, targetCodeSize, sites, assumptions, methods, comments, dataSection, dataSectionAlignment, dataSectionPatches, isImmutablePIC,
-                            totalFrameSize, customStackArea, hsMethod, entryBCI, id, jvmciEnv, hasUnsafeAccess);
+                            totalFrameSize, customStackArea, hsMethod, entryBCI, id, jvmciCompileState, hasUnsafeAccess);
         } else {
             return new HotSpotCompiledCode(name, targetCode, targetCodeSize, sites, assumptions, methods, comments, dataSection, dataSectionAlignment, dataSectionPatches, isImmutablePIC,
                             totalFrameSize, customStackArea);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotDataBuilder.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotDataBuilder.java	Tue Mar 12 19:17:42 2019 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -51,12 +51,6 @@
     }
 
     @Override
-    public boolean needDetailedPatchingInformation() {
-        /* The HotSpot VM finds operands that need patching by decoding the instruction. */
-        return false;
-    }
-
-    @Override
     public Data createDataItem(Constant constant) {
         if (JavaConstant.isNull(constant)) {
             boolean compressed = COMPRESSED_NULL.equals(constant);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java	Tue Mar 12 19:17:42 2019 +0100
@@ -25,6 +25,7 @@
 package org.graalvm.compiler.hotspot;
 
 import static jdk.vm.ci.common.InitTimer.timer;
+import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE;
 import static org.graalvm.compiler.hotspot.HotSpotGraalOptionValues.GRAAL_OPTION_PROPERTY_PREFIX;
 
 import java.io.PrintStream;
@@ -71,7 +72,7 @@
     public void onSelection() {
         JVMCIVersionCheck.check(false);
         assert options == null : "cannot select " + getClass() + " service more than once";
-        options = HotSpotGraalOptionValues.HOTSPOT_OPTIONS;
+        options = HotSpotGraalOptionValues.defaultOptions();
         initializeGraalCompilePolicyFields(options);
         isGraalPredicate = compileGraalWithC1Only ? new IsGraalPredicate() : null;
         /*
@@ -80,6 +81,10 @@
          */
         adjustCompilationLevelInternal(Object.class, "hashCode", "()I", CompilationLevel.FullOptimization);
         adjustCompilationLevelInternal(Object.class, "hashCode", "()I", CompilationLevel.Simple);
+        if (IS_BUILDING_NATIVE_IMAGE) {
+            // Triggers initialization of all option descriptors
+            Options.CompileGraalWithC1Only.getName();
+        }
     }
 
     private static void initializeGraalCompilePolicyFields(OptionValues options) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalJVMCIServiceLocator.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalJVMCIServiceLocator.java	Tue Mar 12 19:17:42 2019 +0100
@@ -26,6 +26,7 @@
 
 import org.graalvm.compiler.serviceprovider.ServiceProvider;
 
+import jdk.vm.ci.common.NativeImageReinitialize;
 import jdk.vm.ci.hotspot.HotSpotVMEventListener;
 import jdk.vm.ci.runtime.JVMCICompilerFactory;
 import jdk.vm.ci.services.JVMCIServiceLocator;
@@ -51,7 +52,7 @@
             return null;
         }
 
-        private HotSpotGraalRuntime graalRuntime;
+        @NativeImageReinitialize private HotSpotGraalRuntime graalRuntime;
 
         /**
          * Notifies this object of the compiler created via {@link HotSpotGraalJVMCIServiceLocator}.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalOptionValues.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalOptionValues.java	Tue Mar 12 19:17:42 2019 +0100
@@ -40,9 +40,10 @@
 import org.graalvm.compiler.options.OptionsParser;
 
 import jdk.vm.ci.common.InitTimer;
+import jdk.vm.ci.common.NativeImageReinitialize;
 
 /**
- * The {@link #HOTSPOT_OPTIONS} value contains the options values initialized in a HotSpot VM. The
+ * The {@link #defaultOptions()} method returns the options values initialized in a HotSpot VM. The
  * values are set via system properties with the {@value #GRAAL_OPTION_PROPERTY_PREFIX} prefix.
  */
 public class HotSpotGraalOptionValues {
@@ -71,7 +72,21 @@
         return GRAAL_OPTION_PROPERTY_PREFIX + value.getName() + "=" + value.getValue(options);
     }
 
-    public static final OptionValues HOTSPOT_OPTIONS = initializeOptions();
+    @NativeImageReinitialize private static volatile OptionValues hotspotOptions;
+
+    public static OptionValues defaultOptions() {
+        OptionValues res = hotspotOptions;
+        if (res == null) {
+            synchronized (HotSpotGraalOptionValues.class) {
+                res = hotspotOptions;
+                if (res == null) {
+                    res = initializeOptions();
+                    hotspotOptions = res;
+                }
+            }
+        }
+        return res;
+    }
 
     /**
      * Global options. The values for these options are initialized by parsing the file denoted by
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java	Tue Mar 12 19:17:42 2019 +0100
@@ -95,6 +95,8 @@
  */
 public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider {
 
+    private static final boolean IS_AOT = Boolean.getBoolean("com.oracle.graalvm.isaot");
+
     private static boolean checkArrayIndexScaleInvariants(MetaAccessProvider metaAccess) {
         assert metaAccess.getArrayIndexScale(JavaKind.Byte) == 1;
         assert metaAccess.getArrayIndexScale(JavaKind.Boolean) == 1;
@@ -159,9 +161,13 @@
         compilerConfigurationName = compilerConfigurationFactory.getName();
 
         compiler = new HotSpotGraalCompiler(jvmciRuntime, this, options);
-        management = GraalServices.loadSingle(HotSpotGraalManagementRegistration.class, false);
-        if (management != null) {
-            management.initialize(this);
+        if (IS_AOT) {
+            management = null;
+        } else {
+            management = GraalServices.loadSingle(HotSpotGraalManagementRegistration.class, false);
+            if (management != null) {
+                management.initialize(this);
+            }
         }
 
         BackendMap backendMap = compilerConfigurationFactory.createBackendMap();
@@ -571,7 +577,7 @@
         EconomicMap<OptionKey<?>, Object> extra = EconomicMap.create();
         extra.put(DebugOptions.Dump, filter);
         extra.put(DebugOptions.PrintGraphHost, host);
-        extra.put(DebugOptions.PrintBinaryGraphPort, port);
+        extra.put(DebugOptions.PrintGraphPort, port);
         OptionValues compileOptions = new OptionValues(getOptions(), extra);
         compiler.compileMethod(new HotSpotCompilationRequest(hotSpotMethod, -1, 0L), false, compileOptions);
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java	Tue Mar 12 19:17:42 2019 +0100
@@ -24,17 +24,34 @@
 
 package org.graalvm.compiler.hotspot;
 
+import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE;
+import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE;
+import static org.graalvm.compiler.replacements.ReplacementsImpl.Options.UseEncodedSnippets;
+
+import java.util.Set;
+
+import jdk.internal.vm.compiler.collections.EconomicSet;
 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
 import org.graalvm.compiler.bytecode.BytecodeProvider;
+import org.graalvm.compiler.core.common.CompilationIdentifier;
+import org.graalvm.compiler.debug.DebugContext;
+import org.graalvm.compiler.debug.GraalError;
+import org.graalvm.compiler.graph.NodeSourcePosition;
 import org.graalvm.compiler.hotspot.meta.HotSpotWordOperationPlugin;
 import org.graalvm.compiler.hotspot.word.HotSpotOperation;
+import org.graalvm.compiler.nodes.Invoke;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderPlugin;
+import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
+import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin;
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.phases.util.Providers;
 import org.graalvm.compiler.printer.GraalDebugHandlersFactory;
 import org.graalvm.compiler.replacements.ReplacementsImpl;
 
 import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.common.NativeImageReinitialize;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 
 /**
@@ -46,21 +63,149 @@
         super(options, new GraalDebugHandlersFactory(snippetReflection), providers, snippetReflection, bytecodeProvider, target);
     }
 
+    protected HotSpotReplacementsImpl(HotSpotReplacementsImpl replacements, Providers providers) {
+        super(replacements.options, new GraalDebugHandlersFactory(replacements.snippetReflection), providers, replacements.snippetReflection,
+                        replacements.getDefaultReplacementBytecodeProvider(), replacements.target);
+    }
+
     @Override
     public Class<? extends GraphBuilderPlugin> getIntrinsifyingPlugin(ResolvedJavaMethod method) {
         return method.getAnnotation(HotSpotOperation.class) != null ? HotSpotWordOperationPlugin.class : super.getIntrinsifyingPlugin(method);
     }
 
+    public void registerMethodSubstitution(ResolvedJavaMethod method, ResolvedJavaMethod original) {
+        if (!IS_IN_NATIVE_IMAGE) {
+            if (IS_BUILDING_NATIVE_IMAGE || UseEncodedSnippets.getValue(options)) {
+                synchronized (HotSpotReplacementsImpl.class) {
+                    if (snippetEncoder == null) {
+                        snippetEncoder = new SymbolicSnippetEncoder(this);
+                    }
+                    snippetEncoder.registerMethodSubstitution(method, original);
+                }
+            }
+        }
+    }
+
+    @Override
+    public StructuredGraph getIntrinsicGraph(ResolvedJavaMethod method, CompilationIdentifier compilationId, DebugContext debug) {
+        if (IS_IN_NATIVE_IMAGE) {
+            HotSpotReplacementsImpl replacements = (HotSpotReplacementsImpl) providers.getReplacements();
+            InvocationPlugin plugin = replacements.getGraphBuilderPlugins().getInvocationPlugins().lookupInvocation(method);
+            if (plugin instanceof MethodSubstitutionPlugin) {
+                MethodSubstitutionPlugin msp = (MethodSubstitutionPlugin) plugin;
+                return replacements.getMethodSubstitution(msp, method);
+            }
+            return null;
+        }
+        return super.getIntrinsicGraph(method, compilationId, debug);
+    }
+
+    @Override
+    public void notifyNotInlined(GraphBuilderContext b, ResolvedJavaMethod method, Invoke invoke) {
+        if (b.parsingIntrinsic() && snippetEncoder != null) {
+            if (getIntrinsifyingPlugin(method) != null) {
+                snippetEncoder.addDelayedInvocationPluginMethod(method);
+                return;
+            }
+        }
+        super.notifyNotInlined(b, method, invoke);
+    }
+
+    // When assertions are enabled, these fields are used to ensure all snippets are
+    // registered during Graal initialization which in turn ensures that native image
+    // building will not miss any snippets.
+    @NativeImageReinitialize private EconomicSet<ResolvedJavaMethod> registeredSnippets = EconomicSet.create();
     private boolean snippetRegistrationClosed;
 
     @Override
     public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition) {
-        assert !snippetRegistrationClosed;
-        super.registerSnippet(method, original, receiver, trackNodeSourcePosition);
+        if (!IS_IN_NATIVE_IMAGE) {
+            assert !snippetRegistrationClosed : "Cannot register snippet after registration is closed: " + method.format("%H.%n(%p)");
+            assert registeredSnippets.add(method) : "Cannot register snippet twice: " + method.format("%H.%n(%p)");
+            if (IS_BUILDING_NATIVE_IMAGE || UseEncodedSnippets.getValue(options)) {
+                synchronized (HotSpotReplacementsImpl.class) {
+                    if (snippetEncoder == null) {
+                        snippetEncoder = new SymbolicSnippetEncoder(this);
+                    }
+                    snippetEncoder.registerSnippet(method, original, receiver, trackNodeSourcePosition);
+                }
+            }
+        }
     }
 
     @Override
     public void closeSnippetRegistration() {
         snippetRegistrationClosed = true;
     }
+
+    static SymbolicSnippetEncoder.EncodedSnippets getEncodedSnippets() {
+        return encodedSnippets;
+    }
+
+    public Set<ResolvedJavaMethod> getSnippetMethods() {
+        if (snippetEncoder != null) {
+            return snippetEncoder.getSnippetMethods();
+        }
+        return null;
+    }
+
+    static void setEncodedSnippets(SymbolicSnippetEncoder.EncodedSnippets encodedSnippets) {
+        HotSpotReplacementsImpl.encodedSnippets = encodedSnippets;
+    }
+
+    public boolean encode() {
+        SymbolicSnippetEncoder encoder = HotSpotReplacementsImpl.snippetEncoder;
+        if (encoder != null) {
+            return encoder.encode();
+        }
+        return false;
+    }
+
+    private static volatile SymbolicSnippetEncoder.EncodedSnippets encodedSnippets;
+
+    @NativeImageReinitialize static SymbolicSnippetEncoder snippetEncoder;
+
+    @Override
+    public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod recursiveEntry, Object[] args, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition) {
+        StructuredGraph graph = getEncodedSnippet(method, args);
+        if (graph != null) {
+            return graph;
+        }
+
+        assert !IS_IN_NATIVE_IMAGE : "should be using encoded snippets";
+        return super.getSnippet(method, recursiveEntry, args, trackNodeSourcePosition, replaceePosition);
+    }
+
+    public StructuredGraph getEncodedSnippet(ResolvedJavaMethod method, Object[] args) {
+        if (IS_IN_NATIVE_IMAGE || UseEncodedSnippets.getValue(options)) {
+            synchronized (HotSpotReplacementsImpl.class) {
+                if (!IS_IN_NATIVE_IMAGE && UseEncodedSnippets.getValue(options)) {
+                    snippetEncoder.encode();
+                }
+
+                if (getEncodedSnippets() == null) {
+                    throw GraalError.shouldNotReachHere("encoded snippets not found");
+                }
+                StructuredGraph graph = getEncodedSnippets().getEncodedSnippet(method, this, args);
+                if (graph == null) {
+                    throw GraalError.shouldNotReachHere("snippet not found: " + method.format("%H.%n(%p)"));
+                }
+                return graph;
+            }
+        } else if (registeredSnippets != null) {
+            assert registeredSnippets.contains(method) : "Asking for snippet method that was never registered: " + method.format("%H.%n(%p)");
+        }
+        return null;
+    }
+
+    public StructuredGraph getMethodSubstitution(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original) {
+        if (IS_IN_NATIVE_IMAGE || UseEncodedSnippets.getValue(options)) {
+            if (getEncodedSnippets() == null) {
+                throw GraalError.shouldNotReachHere("encoded snippets not found");
+            }
+            return getEncodedSnippets().getMethodSubstitutionGraph(plugin, original, this);
+        }
+        return null;
+    }
+
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotTTYStreamProvider.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotTTYStreamProvider.java	Tue Mar 12 19:17:42 2019 +0100
@@ -25,7 +25,7 @@
 package org.graalvm.compiler.hotspot;
 
 import static org.graalvm.compiler.hotspot.HotSpotGraalOptionValues.GRAAL_OPTION_PROPERTY_PREFIX;
-import static org.graalvm.compiler.hotspot.HotSpotGraalOptionValues.HOTSPOT_OPTIONS;
+import static org.graalvm.compiler.hotspot.HotSpotGraalOptionValues.defaultOptions;
 
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
@@ -59,7 +59,7 @@
 
     @Override
     public PrintStream getStream() {
-        return Options.LogFile.getStream(HOTSPOT_OPTIONS);
+        return Options.LogFile.getStream(defaultOptions());
     }
 
     /**
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java	Tue Mar 12 12:12:01 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java	Tue Mar 12 19:17:42 2019 +0100
@@ -38,8 +38,9 @@
  */
 class JVMCIVersionCheck {
 
+    // 0.55 introduces new HotSpotSpeculationLog API
     private static final int JVMCI8_MIN_MAJOR_VERSION = 0;
-    private static final int JVMCI8_MIN_MINOR_VERSION = 46;
+    private static final int JVMCI8_MIN_MINOR_VERSION = 55;
 
     private static void failVersionCheck(boolean exit, String reason, Object... args) {
         Formatter errorMessage = new Formatter().format(reason, args);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java	Tue Mar 12 19:17:42 2019 +0100
@@ -0,0 +1,1034 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 org.graalvm.compiler.hotspot;
+
+import static jdk.vm.ci.runtime.JVMCI.getRuntime;
+import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE;
+import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE;
+import static org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo.createIntrinsicInlineInfo;
+import static org.graalvm.compiler.replacements.ReplacementsImpl.Options.UseEncodedSnippets;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.graalvm.compiler.api.replacements.Fold;
+import org.graalvm.compiler.api.replacements.MethodSubstitution;
+import org.graalvm.compiler.api.replacements.Snippet;
+import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
+import org.graalvm.compiler.api.runtime.GraalJVMCICompiler;
+import org.graalvm.compiler.api.runtime.GraalRuntime;
+import org.graalvm.compiler.bytecode.BytecodeProvider;
+import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
+import org.graalvm.compiler.core.common.type.AbstractObjectStamp;
+import org.graalvm.compiler.core.common.type.Stamp;
+import org.graalvm.compiler.core.common.type.StampPair;
+import org.graalvm.compiler.core.common.type.SymbolicJVMCIReference;
+import org.graalvm.compiler.debug.DebugContext;
+import org.graalvm.compiler.debug.GraalError;
+import org.graalvm.compiler.graph.Node;
+import org.graalvm.compiler.graph.NodeClass;
+import org.graalvm.compiler.graph.NodeMap;
+import org.graalvm.compiler.graph.NodeSourcePosition;
+import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider;
+import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
+import org.graalvm.compiler.java.BytecodeParser;
+import org.graalvm.compiler.java.GraphBuilderPhase;
+import org.graalvm.compiler.nodeinfo.Verbosity;
+import org.graalvm.compiler.nodes.CallTargetNode;
+import org.graalvm.compiler.nodes.ConstantNode;
+import org.graalvm.compiler.nodes.EncodedGraph;
+import org.graalvm.compiler.nodes.FrameState;
+import org.graalvm.compiler.nodes.FullInfopointNode;
+import org.graalvm.compiler.nodes.GraphEncoder;
+import org.graalvm.compiler.nodes.ParameterNode;
+import org.graalvm.compiler.nodes.ProxyNode;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.cfg.Block;
+import org.graalvm.compiler.nodes.graphbuilderconf.GeneratedInvocationPlugin;
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
+import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin;
+import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext;
+import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
+import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
+import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin;
+import org.graalvm.compiler.nodes.graphbuilderconf.NodePlugin;
+import org.graalvm.compiler.nodes.graphbuilderconf.ParameterPlugin;
+import org.graalvm.compiler.nodes.java.AccessFieldNode;
+import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
+import org.graalvm.compiler.nodes.spi.DelegatingReplacements;
+import org.graalvm.compiler.nodes.spi.StampProvider;
+import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
+import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.phases.OptimisticOptimizations;
+import org.graalvm.compiler.phases.schedule.SchedulePhase;
+import org.graalvm.compiler.phases.util.Providers;
+import org.graalvm.compiler.replacements.ConstantBindingParameterPlugin;
+import org.graalvm.compiler.replacements.PEGraphDecoder;
+import org.graalvm.compiler.replacements.ReplacementsImpl;
+import org.graalvm.compiler.replacements.SnippetCounter;
+import org.graalvm.compiler.replacements.SnippetIntegerHistogram;
+
+import jdk.vm.ci.code.Architecture;
+import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaField;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaType;
+import jdk.vm.ci.meta.Constant;
+import jdk.vm.ci.meta.ConstantReflectionProvider;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaType;
+import jdk.vm.ci.meta.MemoryAccessProvider;
+import jdk.vm.ci.meta.MetaAccessProvider;
+import jdk.vm.ci.meta.MethodHandleAccessProvider;
+import jdk.vm.ci.meta.ResolvedJavaField;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.meta.UnresolvedJavaField;
+import jdk.vm.ci.meta.UnresolvedJavaMethod;
+import jdk.vm.ci.meta.UnresolvedJavaType;
+
+/**
+ * This class performs graph encoding using {@link GraphEncoder} but also converts JVMCI type and
+ * method references into a symbolic form that can be resolved at graph decode time using
+ * {@link SymbolicJVMCIReference}.
+ */
+public class SymbolicSnippetEncoder extends DelegatingReplacements {
+
+    /**
+     * This is a customized HotSpotReplacementsImpl intended only for parsing snippets and method
+     * substitutions for graph encoding.
+     */
+    private final HotSpotSnippetReplacementsImpl replacements;
+
+    /**
+     * The set of all snippet methods that have been encoded.
+     */
+    private final Set<ResolvedJavaMethod> snippetMethods = Collections.synchronizedSet(new HashSet<>());
+
+    /**
+     * A mapping from the method substitution method to the original method name. The string key and
+     * values are produced using {@link #methodKey(ResolvedJavaMethod)}.
+     */
+    private final Map<String, String> originalMethods = new ConcurrentHashMap<>();
+
+    /**
+     * The current count of graphs encoded. Used to detect when new graphs have been enqueued for
+     * encoding.
+     */
+    int encodedGraphs = 0;
+
+    /**
+     * All the graphs parsed so far.
+     */
+    private Map<String, StructuredGraph> preparedSnippetGraphs = new HashMap<>();
+
+    /**
+     * The invocation plugins which were delayed during graph preparation.
+     */
+    private Set<ResolvedJavaMethod> delayedInvocationPluginMethods = new HashSet<>();
+
+    void addDelayedInvocationPluginMethod(ResolvedJavaMethod method) {
+        delayedInvocationPluginMethods.add(method);
+    }
+
+    Set<ResolvedJavaMethod> getSnippetMethods() {
+        return snippetMethods;
+    }
+
+    protected class SnippetInlineInvokePlugin implements InlineInvokePlugin {
+
+        @Override
+        public InlineInfo shouldInlineInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) {
+            if (method.getAnnotation(Fold.class) != null) {
+                delayedInvocationPluginMethods.add(method);
+                return InlineInfo.DO_NOT_INLINE_NO_EXCEPTION;
+            }
+
+            if (getIntrinsifyingPlugin(method) != null) {
+                delayedInvocationPluginMethods.add(method);
+                return InlineInfo.DO_NOT_INLINE_NO_EXCEPTION;
+            }
+
+            // Force inlining when parsing replacements
+            return createIntrinsicInlineInfo(method, null, getDefaultReplacementBytecodeProvider());
+        }
+
+        @Override
+        public void notifyAfterInline(ResolvedJavaMethod methodToInline) {
+            assert methodToInline.getAnnotation(Fold.class) == null : methodToInline;
+        }
+    }
+
+    public static class SnippetInvocationPlugins extends InvocationPlugins {
+
+        SnippetInvocationPlugins(InvocationPlugins invocationPlugins) {
+            super(invocationPlugins);
+        }
+
+        @Override
+        public InvocationPlugin lookupInvocation(ResolvedJavaMethod method) {
+            if (method.getAnnotation(Fold.class) != null) {
+                return null;
+            }
+            return super.lookupInvocation(method);
+        }
+    }
+
+    /**
+     * This plugin disables the snippet counter machinery.
+     */
+    private class SnippetCounterPlugin implements NodePlugin {
+        String snippetCounterName = 'L' + SnippetCounter.class.getName().replace('.', '/') + ';';
+        String snippetIntegerHistogramName = 'L' + SnippetIntegerHistogram.class.getName().replace('.', '/') + ';';
+
+        @Override
+        public boolean handleLoadField(GraphBuilderContext b, ValueNode object, ResolvedJavaField field) {
+            if (field.getName().equals("group") && field.getDeclaringClass().getName().equals(snippetCounterName)) {
+                b.addPush(JavaKind.Object, ConstantNode.forConstant(JavaConstant.NULL_POINTER, b.getMetaAccess()));
+                return true;
+            }
+            if (field.getType().getName().equals(snippetCounterName)) {
+                b.addPush(JavaKind.Object, ConstantNode.forConstant(replacements.snippetReflection.forObject(SnippetCounter.DISABLED_COUNTER), b.getMetaAccess()));
+                return true;
+            }
+
+            if (field.getType().getName().equals(snippetIntegerHistogramName)) {
+                b.addPush(JavaKind.Object, ConstantNode.forConstant(replacements.snippetReflection.forObject(SnippetIntegerHistogram.DISABLED_COUNTER), b.getMetaAccess()));
+                return true;
+            }
+            return false;
+        }
+    }
+
+    /**
+     * Generate a String name for a method including all type information. Used as a symbolic key
+     * for lookup.
+     */
+    private static String methodKey(ResolvedJavaMethod method) {
+        return method.format("%f %H.%n(%P)");
+    }
+
+    SymbolicSnippetEncoder(HotSpotReplacementsImpl replacements) {
+        super(replacements);
+
+        GraphBuilderConfiguration.Plugins plugins = replacements.getGraphBuilderPlugins();
+        SnippetInvocationPlugins invocationPlugins = new SnippetInvocationPlugins(plugins.getInvocationPlugins());
+        GraphBuilderConfiguration.Plugins copy = new GraphBuilderConfiguration.Plugins(plugins, invocationPlugins);
+        copy.clearInlineInvokePlugins();
+        copy.appendInlineInvokePlugin(new SnippetInlineInvokePlugin());
+        copy.appendNodePlugin(new SnippetCounterPlugin());
+        HotSpotProviders providers = (HotSpotProviders) replacements.getProviders().copyWith(new HotSpotSubstrateConstantReflectionProvider(replacements.getProviders().getConstantReflection()));
+        this.replacements = new HotSpotSnippetReplacementsImpl(replacements, providers.copyWith(copy));
+        this.replacements.setGraphBuilderPlugins(copy);
+    }
+
+    @Override
+    public GraphBuilderConfiguration.Plugins getGraphBuilderPlugins() {
+        return replacements.getGraphBuilderPlugins();
+    }
+
+    /**
+     * Compiles the snippet and stores the graph.
+     */
+    public void registerMethodSubstitution(ResolvedJavaMethod method, ResolvedJavaMethod original) {
+        assert method.getAnnotation(MethodSubstitution.class) != null : "MethodSubstitution must be annotated with @" + MethodSubstitution.class.getSimpleName();
+        buildGraph(method, original, null, false, false);
+        snippetMethods.add(method);
+    }
+
+    static class EncodedSnippets {
+        private byte[] snippetEncoding;
+        private Object[] snippetObjects;
+        private NodeClass<?>[] snippetNodeClasses;
+        private Map<String, Integer> snippetStartOffsets;
+        private Map<String, String> originalMethods;
+
+        EncodedSnippets(byte[] snippetEncoding, Object[] snippetObjects, NodeClass<?>[] snippetNodeClasses, Map<String, Integer> snippetStartOffsets, Map<String, String> originalMethods) {
+            this.snippetEncoding = snippetEncoding;
+            this.snippetObjects = snippetObjects;
+            this.snippetNodeClasses = snippetNodeClasses;
+            this.snippetStartOffsets = snippetStartOffsets;
+            this.originalMethods = originalMethods;
+        }
+
+        public StructuredGraph getMethodSubstitutionGraph(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, ReplacementsImpl replacements) {
+            Integer startOffset = snippetStartOffsets.get(plugin.toString());
+            if (startOffset == null) {
+                throw GraalError.shouldNotReachHere("plugin graph not found: " + plugin);
+            }
+
+            return decodeGraph(original, null, startOffset, replacements);
+        }
+
+        @SuppressWarnings("try")
+        private StructuredGraph decodeGraph(ResolvedJavaMethod method, Object[] args, int startOffset, ReplacementsImpl replacements) {
+            OptionValues options = replacements.getOptions();
+            SnippetReflectionProvider snippetReflection = replacements.snippetReflection;
+            ParameterPlugin parameterPlugin = null;
+            Providers providers = replacements.getProviders();
+            if (args != null) {
+                parameterPlugin = new ConstantBindingParameterPlugin(args, providers.getMetaAccess(), snippetReflection);
+            }
+
+            EncodedGraph encodedGraph = new SymbolicEncodedGraph(snippetEncoding, startOffset, snippetObjects, snippetNodeClasses, method.getDeclaringClass(),
+                            originalMethods.get(methodKey(method)));
+            try (DebugContext debug = replacements.openDebugContext("SVMSnippet_", method)) {
+                StructuredGraph result = new StructuredGraph.Builder(options, debug).method(method).setIsSubstitution(true).build();
+                PEGraphDecoder graphDecoder = new PEGraphDecoder(
+                                providers.getCodeCache().getTarget().arch,
+                                result,
+                                providers.getMetaAccess(),
+                                providers.getConstantReflection(),
+                                providers.getConstantFieldProvider(),
+                                providers.getStampProvider(),
+                                null, // loopExplosionPlugin
+                                replacements.getGraphBuilderPlugins().getInvocationPlugins(),
+                                new InlineInvokePlugin[0],
+                                parameterPlugin,
+                                null, // nodePlugins
+                                null, // callInlinedMethod
+                                null // sourceLanguagePositionProvider
+                ) {
+                    @Override
+                    protected EncodedGraph lookupEncodedGraph(ResolvedJavaMethod lookupMethod,
+                                    ResolvedJavaMethod originalMethod,
+                                    BytecodeProvider intrinsicBytecodeProvider,
+                                    boolean isSubstitution,
+                                    boolean trackNodeSourcePosition) {
+                        if (lookupMethod.equals(method)) {
+                            return encodedGraph;
+                        } else {
+                            throw GraalError.shouldNotReachHere(method.format("%H.%n(%p)"));
+                        }
+                    }
+                };
+
+                graphDecoder.decode(method, result.isSubstitution(), encodedGraph.trackNodeSourcePosition());
+
+                assert result.verify();
+                return result;
+            }
+        }
+
+        StructuredGraph getEncodedSnippet(ResolvedJavaMethod method, ReplacementsImpl replacements, Object[] args) {
+            Integer startOffset = null;
+            if (snippetStartOffsets != null) {
+                startOffset = snippetStartOffsets.get(methodKey(method));
+            }
+            if (startOffset == null) {
+                if (IS_IN_NATIVE_IMAGE) {
+                    throw GraalError.shouldNotReachHere("snippet not found: " + method.format("%H.%n(%p)"));
+                } else {
+                    return null;
+                }
+            }
+
+            SymbolicEncodedGraph encodedGraph = new SymbolicEncodedGraph(snippetEncoding, startOffset, snippetObjects, snippetNodeClasses, method.getDeclaringClass(),
+                            originalMethods.get(methodKey(method)));
+            return decodeSnippetGraph(encodedGraph, method, replacements, args, HotSpotJVMCIRuntime.runtime().getHostJVMCIBackend().getTarget().arch);
+        }
+
+    }
+
+    private StructuredGraph buildGraph(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean requireInlining, boolean trackNodeSourcePosition) {
+        assert method.hasBytecodes() : "Snippet must not be abstract or native";
+        Object[] args = null;
+        if (receiver != null) {
+            args = new Object[method.getSignature().getParameterCount(true)];
+            args[0] = receiver;
+        }
+        try (DebugContext debug = openDebugContext("Snippet_", method)) {
+            StructuredGraph graph = replacements.makeGraph(debug, replacements.getDefaultReplacementBytecodeProvider(), method, args, original, trackNodeSourcePosition, null);
+
+            // Check if all methods which should be inlined are really inlined.
+            for (MethodCallTargetNode callTarget : graph.getNodes(MethodCallTargetNode.TYPE)) {
+                ResolvedJavaMethod callee = callTarget.targetMethod();
+                if (requireInlining && !delayedInvocationPluginMethods.contains(callee) && !Objects.equals(callee, original)) {
+                    throw GraalError.shouldNotReachHere("method " + callee.format("%H.%n") + " not inlined in snippet " + method.getName() + " (maybe not final?)");
+                }
+            }
+            assert verifySnippetEncodeDecode(method, original, trackNodeSourcePosition, graph);
+            debug.dump(DebugContext.VERBOSE_LEVEL, graph, "After buildGraph");
+            return graph;
+        }
+    }
+
+    @SuppressWarnings("try")
+    static StructuredGraph decodeSnippetGraph(SymbolicEncodedGraph encodedGraph, ResolvedJavaMethod method, ReplacementsImpl replacements, O