changeset 49451:e06f9607f370

8198969: Update Graal Reviewed-by: kvn
author iveresov
date Fri, 16 Mar 2018 22:59:32 -0700
parents 5d2adef239d6
children acb36277a784
files make/CompileToolsHotspot.gmk 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.bytecode/src/org/graalvm/compiler/bytecode/BytecodeDisassembler.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/DisassemblerProvider.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressNode.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.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeLIRBuilder.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/TraceInliningMode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/BiDirectionalTraceBuilder.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/UniDirectionalTraceBuilder.java 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/FloatStamp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/StampFactory.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/BasePhaseBinaryGraphTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalNodeTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CountedLoopTest.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/SwitchDyingLoopTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TrivialInliningExplosionTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsignedLongTest.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/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/target/Backend.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/.checkstyle_checks.xml src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/InlineCacheGuardPosition.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.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.graph/src/org/graalvm/compiler/graph/NodeSourcePosition.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/SourceLanguagePosition.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/SourceLanguagePositionProvider.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/AArch64HotSpotDeoptimizeOp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMove.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/StubAVXTest.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/AMD64HotSpotArithmeticLIRGenerator.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/AMD64HotSpotMaths.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/CompileTheWorld.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotLazyInitializationTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.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/HotSpotGraalCompilerFactory.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/NodeCostDumpUtil.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/lir/VerifyMaxRegisterSizePhase.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/HotSpotGraphBuilderPlugins.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvocationPlugins.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/AOTInliningPolicy.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/AssertionSnippets.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HashCodeSnippets.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/LoadExceptionObjectSnippets.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.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/ObjectCloneNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/StringToBytesSnippets.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/UnsafeLoadSnippets.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/replacements/aot/ResolveConstantSnippets.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProbabilisticProfileSnippets.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProfileSnippets.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallStub.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/BytecodeParserOptions.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/JTTTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotpath/HP_series.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/Math_abs.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/Math_cos.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/Math_exp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/Math_log.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/Math_pow.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/Math_sin.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/Math_sqrt.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/Math_tan.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/UnaryMath.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.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayCompareToOp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64LFenceOp.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/src/org/graalvm/compiler/lir/LIRInstructionClass.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/GlobalLivenessInfo.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TraceAssertions.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TraceGlobalMoveResolutionPhase.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TraceUtil.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TrivialTraceAllocator.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/bu/BottomUpAllocator.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLinearScanLifetimeAnalysisPhase.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/phases/LIRPhaseSuite.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/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/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/MathUtil.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/IntegerStampTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/PrimitiveStampBoundaryTest.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/BeginNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/DeoptimizeNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/DynamicPiNode.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/FixedGuardNode.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/GuardNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InliningLog.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/Invokable.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/Invoke.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeWithExceptionNode.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/StaticDeoptimizingNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/CompareNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ConditionalNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerConvertNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerLowerThanNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/IntegerSwitchNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/ClassInitializationPlugin.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/InlineInvokePlugin.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/IntrinsicContext.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/InstanceOfDynamicNode.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.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.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/NodeCounterPhase.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/AbstractInlineInfo.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/elem/Inlineable.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/elem/InlineableGraph.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/GreedyInliningPolicy.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/InlineMethodSubstitutionsPolicy.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/PhaseSuite.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/contract/VerifyNodeCosts.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinter.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/AArch64FloatArithmeticSnippets.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64IntegerArithmeticSnippets.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64ConvertSnippets.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/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.test/src/org/graalvm/compiler/replacements/test/MethodSubstitutionTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PEGraphDecoderTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/SnippetsTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StandardMethodSubstitutionsTest.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/StringSubstitutionsTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/WordTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/BoxingSnippets.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/ConstantStringIndexOfSnippets.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/InlineDuringParsingPlugin.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/InstanceOfSnippetsTemplates.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/SnippetCounterNode.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/StringSubstitutions.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileBytecodeProvider.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/MacroNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroStateSplitNode.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/JDK9Method.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.micro.benchmarks/src/micro/benchmarks/StringBenchmark.java
diffstat 191 files changed, 5841 insertions(+), 1620 deletions(-) [+]
line wrap: on
line diff
--- a/make/CompileToolsHotspot.gmk	Fri Mar 16 11:26:05 2018 +0000
+++ b/make/CompileToolsHotspot.gmk	Fri Mar 16 22:59:32 2018 -0700
@@ -120,6 +120,7 @@
       SRC := \
           $(SRC_DIR)/org.graalvm.word/src \
           $(SRC_DIR)/org.graalvm.collections/src \
+          $(SRC_DIR)/org.graalvm.compiler.bytecode/src \
           $(SRC_DIR)/org.graalvm.compiler.replacements.verifier/src \
           $(SRC_DIR)/org.graalvm.compiler.api.replacements/src \
           $(SRC_DIR)/org.graalvm.compiler.code/src \
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java	Fri Mar 16 22:59:32 2018 -0700
@@ -195,11 +195,6 @@
         private static final int VEX_W = 0x80;
     }
 
-    private static class AvxVectorLen {
-        private static final int AVX_128bit = 0x0;
-        private static final int AVX_256bit = 0x1;
-    }
-
     private static class VexSimdPrefix {
         private static final int VEX_SIMD_NONE = 0x0;
         private static final int VEX_SIMD_66 = 0x1;
@@ -208,11 +203,44 @@
     }
 
     private static class VexOpcode {
+        private static final int VEX_OPCODE_NONE = 0x0;
         private static final int VEX_OPCODE_0F = 0x1;
         private static final int VEX_OPCODE_0F_38 = 0x2;
         private static final int VEX_OPCODE_0F_3A = 0x3;
     }
 
+    public static class AvxVectorLen {
+        public static final int AVX_128bit = 0x0;
+        public static final int AVX_256bit = 0x1;
+        public static final int AVX_512bit = 0x2;
+        public static final int AVX_NoVec = 0x4;
+    }
+
+    public static class EvexTupleType {
+        public static final int EVEX_FV = 0;
+        public static final int EVEX_HV = 4;
+        public static final int EVEX_FVM = 6;
+        public static final int EVEX_T1S = 7;
+        public static final int EVEX_T1F = 11;
+        public static final int EVEX_T2 = 13;
+        public static final int EVEX_T4 = 15;
+        public static final int EVEX_T8 = 17;
+        public static final int EVEX_HVM = 18;
+        public static final int EVEX_QVM = 19;
+        public static final int EVEX_OVM = 20;
+        public static final int EVEX_M128 = 21;
+        public static final int EVEX_DUP = 22;
+        public static final int EVEX_ETUP = 23;
+    }
+
+    public static class EvexInputSizeInBits {
+        public static final int EVEX_8bit = 0;
+        public static final int EVEX_16bit = 1;
+        public static final int EVEX_32bit = 2;
+        public static final int EVEX_64bit = 3;
+        public static final int EVEX_NObit = 4;
+    }
+
     private AMD64InstructionAttr curAttributes;
 
     AMD64InstructionAttr getCurAttributes() {
@@ -873,6 +901,7 @@
                         opc = VexOpcode.VEX_OPCODE_0F_3A;
                         break;
                     default:
+                        opc = VexOpcode.VEX_OPCODE_NONE;
                         isSimd = false;
                         break;
                 }
@@ -1770,6 +1799,13 @@
         emitOperandHelper(dst, src, 0);
     }
 
+    public final void bsfq(Register dst, Register src) {
+        int encode = prefixqAndEncode(dst.encoding(), src.encoding());
+        emitByte(0x0F);
+        emitByte(0xBC);
+        emitByte(0xC0 | encode);
+    }
+
     public final void bsrl(Register dst, Register src) {
         int encode = prefixAndEncode(dst.encoding(), src.encoding());
         emitByte(0x0F);
@@ -1857,6 +1893,26 @@
         emitByte(0xC0 | encode);
     }
 
+    public final void evmovdquq(Register dst, AMD64Address src, int vectorLen) {
+        assert supports(CPUFeature.AVX512F);
+        AMD64InstructionAttr attributes = new AMD64InstructionAttr(vectorLen, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true, target);
+        attributes.setAddressAttributes(/* tuple_type */ EvexTupleType.EVEX_FVM, /* input_size_in_bits */ EvexInputSizeInBits.EVEX_NObit);
+        attributes.setIsEvexInstruction();
+        vexPrefix(src, Register.None, dst, VexSimdPrefix.VEX_SIMD_F3, VexOpcode.VEX_OPCODE_0F, attributes);
+        emitByte(0x6F);
+        emitOperandHelper(dst, src, 0);
+    }
+
+    public final void evpcmpeqb(Register kdst, Register nds, AMD64Address src, int vectorLen) {
+        assert supports(CPUFeature.AVX512BW);
+        AMD64InstructionAttr attributes = new AMD64InstructionAttr(vectorLen, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false, target);
+        attributes.setIsEvexInstruction();
+        attributes.setAddressAttributes(/* tuple_type */ EvexTupleType.EVEX_FVM, /* input_size_in_bits */ EvexInputSizeInBits.EVEX_NObit);
+        vexPrefix(src, nds, kdst, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
+        emitByte(0x74);
+        emitOperandHelper(kdst, src, 0);
+    }
+
     public final void hlt() {
         emitByte(0xF4);
     }
@@ -1982,6 +2038,32 @@
         }
     }
 
+    // This instruction produces ZF or CF flags
+    public final void kortestql(Register src1, Register src2) {
+        assert supports(CPUFeature.AVX512BW);
+        AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rex_w */ true, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false, target);
+        int encode = vexPrefixAndEncode(src1, Register.None, src2, VexSimdPrefix.VEX_SIMD_NONE, VexOpcode.VEX_OPCODE_0F, attributes);
+        emitByte(0x98);
+        emitByte(0xC0 | encode);
+    }
+
+    public final void kmovql(Register dst, Register src) {
+        assert supports(CPUFeature.AVX512BW);
+        if (src.getRegisterCategory().equals(AMD64.MASK)) {
+            // kmovql(KRegister dst, KRegister src)
+            AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rex_w */ true, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false, target);
+            int encode = vexPrefixAndEncode(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_NONE, VexOpcode.VEX_OPCODE_0F, attributes);
+            emitByte(0x90);
+            emitByte(0xC0 | encode);
+        } else {
+            // kmovql(KRegister dst, Register src)
+            AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rex_w */ true, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false, target);
+            int encode = vexPrefixAndEncode(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_F2, VexOpcode.VEX_OPCODE_0F, attributes);
+            emitByte(0x92);
+            emitByte(0xC0 | encode);
+        }
+    }
+
     public final void lead(Register dst, AMD64Address src) {
         prefix(src, dst);
         emitByte(0x8D);
@@ -2050,6 +2132,15 @@
         emitOperandHelper(dst, src, 0);
     }
 
+    /**
+     * @param wide use 4 byte encoding for displacements that would normally fit in a byte
+     */
+    public final void movl(Register dst, AMD64Address src, boolean wide) {
+        prefix(src, dst);
+        emitByte(0x8B);
+        emitOperandHelper(dst, src, wide, 0);
+    }
+
     public final void movl(AMD64Address dst, int imm32) {
         prefix(dst);
         emitByte(0xC7);
@@ -2291,6 +2382,10 @@
         NOT.emit(this, DWORD, dst);
     }
 
+    public final void notq(Register dst) {
+        NOT.emit(this, QWORD, dst);
+    }
+
     @Override
     public final void ensureUniquePC() {
         nop();
@@ -2540,7 +2635,7 @@
         emitByte(0xC0 | encode);
     }
 
-    void pcmpestri(Register dst, AMD64Address src, int imm8) {
+    public final void pcmpestri(Register dst, AMD64Address src, int imm8) {
         assert supports(CPUFeature.SSE4_2);
         AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
         simdPrefix(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F_3A, attributes);
@@ -2549,7 +2644,7 @@
         emitByte(imm8);
     }
 
-    void pcmpestri(Register dst, Register src, int imm8) {
+    public final void pcmpestri(Register dst, Register src, int imm8) {
         assert supports(CPUFeature.SSE4_2);
         AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
         int encode = simdPrefixAndEncode(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F_3A, attributes);
@@ -2558,6 +2653,26 @@
         emitByte(imm8);
     }
 
+    public final void pmovzxbw(Register dst, AMD64Address src) {
+        assert supports(CPUFeature.SSE4_2);
+        // XXX legacy_mode should be: _legacy_mode_bw
+        AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false, target);
+        attributes.setAddressAttributes(/* tuple_type */ EvexTupleType.EVEX_HVM, /* input_size_in_bits */ EvexInputSizeInBits.EVEX_NObit);
+        simdPrefix(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F_38, attributes);
+        emitByte(0x30);
+        emitOperandHelper(dst, src, 0);
+    }
+
+    public final void vpmovzxbw(Register dst, AMD64Address src, int vectorLen) {
+        assert supports(CPUFeature.AVX);
+        // XXX legacy_mode should be: _legacy_mode_bw
+        AMD64InstructionAttr attributes = new AMD64InstructionAttr(vectorLen, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false, target);
+        attributes.setAddressAttributes(/* tuple_type */ EvexTupleType.EVEX_HVM, /* input_size_in_bits */ EvexInputSizeInBits.EVEX_NObit);
+        vexPrefix(src, Register.None, dst, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F_38, attributes);
+        emitByte(0x30);
+        emitOperandHelper(dst, src, 0);
+    }
+
     public final void push(Register src) {
         int encode = prefixAndEncode(src.encoding);
         emitByte(0x50 | encode);
@@ -2634,6 +2749,15 @@
         emitByte(0xC0 | encode);
     }
 
+    public final void vpxor(Register dst, Register nds, AMD64Address src) {
+        assert supports(CPUFeature.AVX);
+        AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_256bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true, target);
+        attributes.setAddressAttributes(/* tuple_type */ EvexTupleType.EVEX_FV, /* input_size_in_bits */ EvexInputSizeInBits.EVEX_32bit);
+        vexPrefix(src, nds, dst, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
+        emitByte(0xEF);
+        emitOperandHelper(dst, src, 0);
+    }
+
     public final void pslld(Register dst, int imm8) {
         assert isUByte(imm8) : "invalid value";
         assert dst.getRegisterCategory().equals(AMD64.XMM);
@@ -3843,4 +3967,11 @@
         emitByte(0x0f);
         emitByte(0x0b);
     }
+
+    public void lfence() {
+        emitByte(0x0f);
+        emitByte(0xae);
+        emitByte(0xe8);
+
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.bytecode/src/org/graalvm/compiler/bytecode/BytecodeDisassembler.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.bytecode/src/org/graalvm/compiler/bytecode/BytecodeDisassembler.java	Fri Mar 16 22:59:32 2018 -0700
@@ -321,4 +321,61 @@
         }
         // @formatter:on
     }
+
+    public static JavaMethod getInvokedMethodAt(ResolvedJavaMethod method, int invokeBci) {
+        if (method.getCode() == null) {
+            return null;
+        }
+        ConstantPool cp = method.getConstantPool();
+        BytecodeStream stream = new BytecodeStream(method.getCode());
+        int opcode = stream.currentBC();
+        while (opcode != Bytecodes.END) {
+            int bci = stream.currentBCI();
+            if (bci == invokeBci) {
+                if (stream.nextBCI() > bci + 1) {
+                    switch (opcode) {
+                        case INVOKEVIRTUAL:
+                        case INVOKESPECIAL:
+                        case INVOKESTATIC: {
+                            int cpi = stream.readCPI();
+                            JavaMethod callee = cp.lookupMethod(cpi, opcode);
+                            return callee;
+                        }
+                        case INVOKEINTERFACE: {
+                            int cpi = stream.readCPI();
+                            JavaMethod callee = cp.lookupMethod(cpi, opcode);
+                            return callee;
+                        }
+                        case INVOKEDYNAMIC: {
+                            int cpi = stream.readCPI4();
+                            JavaMethod callee = cp.lookupMethod(cpi, opcode);
+                            return callee;
+                        }
+                        default:
+                            throw new InternalError(BytecodeDisassembler.disassembleOne(method, invokeBci));
+                    }
+                }
+            }
+            stream.next();
+            opcode = stream.currentBC();
+        }
+        return null;
+    }
+
+    public static int getBytecodeAt(ResolvedJavaMethod method, int invokeBci) {
+        if (method.getCode() == null) {
+            return -1;
+        }
+        BytecodeStream stream = new BytecodeStream(method.getCode());
+        int opcode = stream.currentBC();
+        while (opcode != Bytecodes.END) {
+            int bci = stream.currentBCI();
+            if (bci == invokeBci) {
+                return opcode;
+            }
+            stream.next();
+            opcode = stream.currentBC();
+        }
+        return -1;
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/DisassemblerProvider.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/DisassemblerProvider.java	Fri Mar 16 22:59:32 2018 -0700
@@ -58,7 +58,7 @@
     }
 
     /**
-     * Gets the name denoting the format of the disassmembly return by this object.
+     * Gets the name denoting the format of the disassembly returned by this object.
      */
     String getName();
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressNode.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressNode.java	Fri Mar 16 22:59:32 2018 -0700
@@ -25,6 +25,7 @@
 
 import org.graalvm.compiler.asm.amd64.AMD64Address.Scale;
 import org.graalvm.compiler.core.common.LIRKind;
+import org.graalvm.compiler.core.common.type.IntegerStamp;
 import org.graalvm.compiler.graph.NodeClass;
 import org.graalvm.compiler.graph.spi.Simplifiable;
 import org.graalvm.compiler.graph.spi.SimplifierTool;
@@ -72,7 +73,7 @@
     }
 
     public void canonicalizeIndex(SimplifierTool tool) {
-        if (index instanceof AddNode) {
+        if (index instanceof AddNode && ((IntegerStamp) index.stamp(NodeView.DEFAULT)).getBits() == 64) {
             AddNode add = (AddNode) index;
             ValueNode valX = add.getX();
             if (valX instanceof PhiNode) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java	Fri Mar 16 22:59:32 2018 -0700
@@ -66,15 +66,14 @@
 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 static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp.UnaryIntrinsicOpcode.EXP;
-import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicBinaryOp.BinaryIntrinsicOpcode.POW;
 
-import org.graalvm.compiler.core.common.NumUtil;
 import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic;
 import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp;
 import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MOp;
@@ -83,10 +82,11 @@
 import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp;
 import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RRMOp;
 import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64Shift;
+import org.graalvm.compiler.asm.amd64.AMD64Assembler.AVXOp;
 import org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize;
 import org.graalvm.compiler.asm.amd64.AMD64Assembler.SSEOp;
-import org.graalvm.compiler.asm.amd64.AMD64Assembler.AVXOp;
 import org.graalvm.compiler.core.common.LIRKind;
+import org.graalvm.compiler.core.common.NumUtil;
 import org.graalvm.compiler.core.common.calc.FloatConvert;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.lir.ConstantValue;
@@ -107,6 +107,7 @@
 import org.graalvm.compiler.lir.amd64.AMD64SignExtendOp;
 import org.graalvm.compiler.lir.amd64.AMD64Unary;
 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;
@@ -114,6 +115,7 @@
 import jdk.vm.ci.code.CodeUtil;
 import jdk.vm.ci.code.Register;
 import jdk.vm.ci.code.RegisterValue;
+import jdk.vm.ci.code.TargetDescription;
 import jdk.vm.ci.meta.AllocatableValue;
 import jdk.vm.ci.meta.Constant;
 import jdk.vm.ci.meta.JavaConstant;
@@ -122,7 +124,6 @@
 import jdk.vm.ci.meta.VMConstant;
 import jdk.vm.ci.meta.Value;
 import jdk.vm.ci.meta.ValueKind;
-import jdk.vm.ci.code.TargetDescription;
 
 /**
  * This class implements the AMD64 specific portion of the LIR generator.
@@ -131,6 +132,40 @@
 
     private static final RegisterValue RCX_I = AMD64.rcx.asValue(LIRKind.value(AMD64Kind.DWORD));
 
+    public AMD64ArithmeticLIRGenerator(Maths maths) {
+        this.maths = maths == null ? new Maths() {
+        } : maths;
+    }
+
+    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) {
         AllocatableValue input = getLIRGen().asAllocatable(inputVal);
@@ -1042,33 +1077,49 @@
 
     @Override
     public Value emitMathLog(Value input, boolean base10) {
-        Variable result = getLIRGen().newVariable(LIRKind.combine(input));
-        AllocatableValue stackSlot = getLIRGen().getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(AMD64Kind.QWORD));
-        getLIRGen().append(new AMD64MathIntrinsicUnaryOp(getAMD64LIRGen(), base10 ? LOG10 : LOG, result, getLIRGen().asAllocatable(input), stackSlot));
+        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, gen.asAllocatable(input), stackSlot));
+        }
         return result;
     }
 
     @Override
     public Value emitMathCos(Value input) {
-        Variable result = getLIRGen().newVariable(LIRKind.combine(input));
-        AllocatableValue stackSlot = getLIRGen().getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(AMD64Kind.QWORD));
-        getLIRGen().append(new AMD64MathIntrinsicUnaryOp(getAMD64LIRGen(), COS, result, getLIRGen().asAllocatable(input), stackSlot));
+        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, gen.asAllocatable(input), stackSlot));
+        }
         return result;
     }
 
     @Override
     public Value emitMathSin(Value input) {
-        Variable result = getLIRGen().newVariable(LIRKind.combine(input));
-        AllocatableValue stackSlot = getLIRGen().getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(AMD64Kind.QWORD));
-        getLIRGen().append(new AMD64MathIntrinsicUnaryOp(getAMD64LIRGen(), SIN, result, getLIRGen().asAllocatable(input), stackSlot));
+        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, gen.asAllocatable(input), stackSlot));
+        }
         return result;
     }
 
     @Override
     public Value emitMathTan(Value input) {
-        Variable result = getLIRGen().newVariable(LIRKind.combine(input));
-        AllocatableValue stackSlot = getLIRGen().getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(AMD64Kind.QWORD));
-        getLIRGen().append(new AMD64MathIntrinsicUnaryOp(getAMD64LIRGen(), TAN, result, getLIRGen().asAllocatable(input), stackSlot));
+        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, gen.asAllocatable(input), stackSlot));
+        }
         return result;
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java	Fri Mar 16 22:59:32 2018 -0700
@@ -59,6 +59,7 @@
 import org.graalvm.compiler.lir.Variable;
 import org.graalvm.compiler.lir.amd64.AMD64AddressValue;
 import org.graalvm.compiler.lir.amd64.AMD64ArithmeticLIRGeneratorTool;
+import org.graalvm.compiler.lir.amd64.AMD64ArrayCompareToOp;
 import org.graalvm.compiler.lir.amd64.AMD64ArrayEqualsOp;
 import org.graalvm.compiler.lir.amd64.AMD64Binary;
 import org.graalvm.compiler.lir.amd64.AMD64BinaryConsumer;
@@ -74,6 +75,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.AMD64LFenceOp;
 import org.graalvm.compiler.lir.amd64.AMD64Move;
 import org.graalvm.compiler.lir.amd64.AMD64Move.CompareAndSwapOp;
 import org.graalvm.compiler.lir.amd64.AMD64Move.MembarOp;
@@ -490,6 +492,20 @@
     }
 
     @Override
+    public Variable emitArrayCompareTo(JavaKind kind1, JavaKind kind2, Value array1, Value array2, Value length1, Value length2) {
+        LIRKind resultKind = LIRKind.value(AMD64Kind.DWORD);
+        RegisterValue raxRes = AMD64.rax.asValue(resultKind);
+        RegisterValue cnt1 = AMD64.rcx.asValue(length1.getValueKind());
+        RegisterValue cnt2 = AMD64.rdx.asValue(length2.getValueKind());
+        emitMove(cnt1, length1);
+        emitMove(cnt2, length2);
+        append(new AMD64ArrayCompareToOp(this, kind1, kind2, raxRes, array1, array2, cnt1, cnt2));
+        Variable result = newVariable(resultKind);
+        emitMove(result, raxRes);
+        return result;
+    }
+
+    @Override
     public Variable emitArrayEquals(JavaKind kind, Value array1, Value array2, Value length) {
         Variable result = newVariable(LIRKind.value(AMD64Kind.DWORD));
         append(new AMD64ArrayEqualsOp(this, kind, result, array1, array2, asAllocatable(length)));
@@ -554,4 +570,8 @@
     public LIRInstruction createZapArgumentSpace(StackSlot[] zappedStack, JavaConstant[] zapValues) {
         return new AMD64ZapStackOp(zappedStack, zapValues);
     }
+
+    public void emitLFence() {
+        append(new AMD64LFenceOp());
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeLIRBuilder.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeLIRBuilder.java	Fri Mar 16 22:59:32 2018 -0700
@@ -23,6 +23,8 @@
 
 package org.graalvm.compiler.core.amd64;
 
+import static org.graalvm.compiler.core.amd64.AMD64NodeLIRBuilder.Options.MitigateSpeculativeExecutionAttacks;
+
 import org.graalvm.compiler.core.gen.NodeLIRBuilder;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.lir.LIRFrameState;
@@ -37,6 +39,11 @@
 import org.graalvm.compiler.nodes.ValueNode;
 import org.graalvm.compiler.nodes.calc.IntegerDivRemNode;
 import org.graalvm.compiler.nodes.calc.IntegerDivRemNode.Op;
+import org.graalvm.compiler.nodes.cfg.Block;
+import org.graalvm.compiler.options.Option;
+import org.graalvm.compiler.options.OptionKey;
+import org.graalvm.compiler.options.OptionType;
+import org.graalvm.compiler.options.OptionValues;
 
 import jdk.vm.ci.amd64.AMD64;
 import jdk.vm.ci.meta.AllocatableValue;
@@ -44,6 +51,13 @@
 
 public abstract class AMD64NodeLIRBuilder extends NodeLIRBuilder {
 
+    public static class Options {
+        // @formatter:off
+        @Option(help = "AMD64: Emit lfence instructions at the beginning of basic blocks", type = OptionType.Expert)
+        public static final OptionKey<Boolean> MitigateSpeculativeExecutionAttacks = new OptionKey<>(false);
+        // @formatter:on
+    }
+
     public AMD64NodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool gen, AMD64NodeMatchRules nodeMatchRules) {
         super(graph, gen, nodeMatchRules);
     }
@@ -121,4 +135,21 @@
     public AMD64LIRGenerator getLIRGeneratorTool() {
         return (AMD64LIRGenerator) gen;
     }
+
+    @Override
+    public void doBlockPrologue(Block block, OptionValues options) {
+        if (MitigateSpeculativeExecutionAttacks.getValue(options)) {
+            boolean hasControlSplitPredecessor = false;
+            for (Block b : block.getPredecessors()) {
+                if (b.getSuccessorCount() > 1) {
+                    hasControlSplitPredecessor = true;
+                    break;
+                }
+            }
+            boolean isStartBlock = block.getPredecessorCount() == 0;
+            if (hasControlSplitPredecessor || isStartBlock) {
+                getLIRGeneratorTool().emitLFence();
+            }
+        }
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java	Fri Mar 16 22:59:32 2018 -0700
@@ -259,6 +259,9 @@
     @Option(help = "", type = OptionType.Debug)
     public static final OptionKey<Boolean> OptDevirtualizeInvokesOptimistically = new OptionKey<>(true);
 
+    @Option(help = "Track the NodeSourcePosition.", type = OptionType.Debug)
+    public static final OptionKey<Boolean> TrackNodeSourcePosition = new OptionKey<>(false);
+
     @Option(help = "Allow backend to match complex expressions.", type = OptionType.Debug)
     public static final OptionKey<Boolean> MatchExpressions = new OptionKey<>(true);
 
@@ -273,8 +276,7 @@
 
     @Option(help = "Enable experimental Trace Register Allocation.", type = OptionType.Debug)
     public static final OptionKey<Boolean> TraceRA = new OptionKey<>(false);
-
-    @Option(help = "How to trace inlining decisions, one of: None, Linear, Tree", type = OptionType.Debug)
-    public static final OptionKey<TraceInliningMode> TraceInlining = new OptionKey<>(TraceInliningMode.None);
+    @Option(help = "Enable tracing of inlining decision.", type = OptionType.Debug)
+    public static final OptionKey<Boolean> TraceInlining = new OptionKey<>(false);
 
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/TraceInliningMode.java	Fri Mar 16 11:26:05 2018 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/*
- * 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;
-
-public enum TraceInliningMode {
-    None(false),
-    Linear(true),
-    Tree(true);
-
-    private final boolean tracing;
-
-    TraceInliningMode(boolean tracing) {
-        this.tracing = tracing;
-    }
-
-    public boolean isTracing() {
-        return tracing;
-    }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/BiDirectionalTraceBuilder.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/BiDirectionalTraceBuilder.java	Fri Mar 16 22:59:32 2018 -0700
@@ -84,7 +84,7 @@
             AbstractBlockBase<?> block = worklist.pollFirst();
             assert block != null;
             if (!processed(block)) {
-                Trace trace = new Trace(startTrace(debug, block));
+                Trace trace = new Trace(findTrace(debug, block));
                 for (AbstractBlockBase<?> traceBlock : trace.getBlocks()) {
                     blockToTrace[traceBlock.getId()] = trace;
                 }
@@ -101,13 +101,13 @@
      * @param debug
      */
     @SuppressWarnings("try")
-    private Collection<AbstractBlockBase<?>> startTrace(DebugContext debug, AbstractBlockBase<?> block) {
+    private Collection<AbstractBlockBase<?>> findTrace(DebugContext debug, AbstractBlockBase<?> initBlock) {
         ArrayDeque<AbstractBlockBase<?>> trace = new ArrayDeque<>();
-        try (Indent i = debug.logAndIndent("StartTrace: %s", block)) {
+        try (Indent i = debug.logAndIndent("StartTrace: %s", initBlock)) {
             try (Indent indentFront = debug.logAndIndent("Head:")) {
-                for (AbstractBlockBase<?> currentBlock = block; currentBlock != null; currentBlock = selectPredecessor(currentBlock)) {
-                    addBlockToTrace(debug, currentBlock);
-                    trace.addFirst(currentBlock);
+                for (AbstractBlockBase<?> block = initBlock; block != null; block = selectPredecessor(block)) {
+                    addBlockToTrace(debug, block);
+                    trace.addFirst(block);
                 }
             }
             /* Number head blocks. Can not do this in the loop as we go backwards. */
@@ -117,11 +117,11 @@
             }
 
             try (Indent indentBack = debug.logAndIndent("Tail:")) {
-                for (AbstractBlockBase<?> currentBlock = selectSuccessor(block); currentBlock != null; currentBlock = selectSuccessor(currentBlock)) {
-                    addBlockToTrace(debug, currentBlock);
-                    trace.addLast(currentBlock);
+                for (AbstractBlockBase<?> block = selectSuccessor(initBlock); block != null; block = selectSuccessor(block)) {
+                    addBlockToTrace(debug, block);
+                    trace.addLast(block);
                     /* This time we can number the blocks immediately as we go forwards. */
-                    currentBlock.setLinearScanNumber(blockNr++);
+                    block.setLinearScanNumber(blockNr++);
                 }
             }
         }
@@ -129,18 +129,18 @@
         return trace;
     }
 
-    private void addBlockToTrace(DebugContext debug, AbstractBlockBase<?> currentBlock) {
-        debug.log("add %s (prob: %f)", currentBlock, currentBlock.probability());
-        processed.set(currentBlock.getId());
+    private void addBlockToTrace(DebugContext debug, AbstractBlockBase<?> block) {
+        debug.log("add %s (prob: %f)", block, block.probability());
+        processed.set(block.getId());
     }
 
     /**
      * @return The unprocessed predecessor with the highest probability, or {@code null}.
      */
-    private AbstractBlockBase<?> selectPredecessor(AbstractBlockBase<?> currentBlock) {
+    private AbstractBlockBase<?> selectPredecessor(AbstractBlockBase<?> block) {
         AbstractBlockBase<?> next = null;
-        for (AbstractBlockBase<?> pred : currentBlock.getPredecessors()) {
-            if (!processed(pred) && !isBackEdge(pred, currentBlock) && (next == null || pred.probability() > next.probability())) {
+        for (AbstractBlockBase<?> pred : block.getPredecessors()) {
+            if (!processed(pred) && !isBackEdge(pred, block) && (next == null || pred.probability() > next.probability())) {
                 next = pred;
             }
         }
@@ -155,9 +155,9 @@
     /**
      * @return The unprocessed successor with the highest probability, or {@code null}.
      */
-    private AbstractBlockBase<?> selectSuccessor(AbstractBlockBase<?> currentBlock) {
+    private AbstractBlockBase<?> selectSuccessor(AbstractBlockBase<?> block) {
         AbstractBlockBase<?> next = null;
-        for (AbstractBlockBase<?> succ : currentBlock.getSuccessors()) {
+        for (AbstractBlockBase<?> succ : block.getSuccessors()) {
             if (!processed(succ) && (next == null || succ.probability() > next.probability())) {
                 next = succ;
             }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/UniDirectionalTraceBuilder.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/UniDirectionalTraceBuilder.java	Fri Mar 16 22:59:32 2018 -0700
@@ -33,7 +33,7 @@
 import org.graalvm.compiler.debug.Indent;
 
 /**
- * Computes traces by starting at a trace head and keep adding predecessors as long as possible.
+ * Computes traces by starting at a trace head and keep adding successors as long as possible.
  */
 public final class UniDirectionalTraceBuilder {
 
@@ -87,7 +87,7 @@
             AbstractBlockBase<?> block = worklist.poll();
             assert block != null;
             if (!processed(block)) {
-                Trace trace = new Trace(startTrace(debug, block));
+                Trace trace = new Trace(findTrace(debug, block));
                 for (AbstractBlockBase<?> traceBlock : trace.getBlocks()) {
                     blockToTrace[traceBlock.getId()] = trace;
                 }
@@ -102,17 +102,17 @@
      * Build a new trace starting at {@code block}.
      */
     @SuppressWarnings("try")
-    private List<AbstractBlockBase<?>> startTrace(DebugContext debug, AbstractBlockBase<?> block) {
-        assert checkPredecessorsProcessed(block);
+    private List<AbstractBlockBase<?>> findTrace(DebugContext debug, AbstractBlockBase<?> traceStart) {
+        assert checkPredecessorsProcessed(traceStart);
         ArrayList<AbstractBlockBase<?>> trace = new ArrayList<>();
         int blockNumber = 0;
-        try (Indent i = debug.logAndIndent("StartTrace: %s", block)) {
-            for (AbstractBlockBase<?> currentBlock = block; currentBlock != null; currentBlock = selectNext(currentBlock)) {
-                debug.log("add %s (prob: %f)", currentBlock, currentBlock.probability());
-                processed.set(currentBlock.getId());
-                trace.add(currentBlock);
-                unblock(currentBlock);
-                currentBlock.setLinearScanNumber(blockNumber++);
+        try (Indent i = debug.logAndIndent("StartTrace: %s", traceStart)) {
+            for (AbstractBlockBase<?> block = traceStart; block != null; block = selectNext(block)) {
+                debug.log("add %s (prob: %f)", block, block.probability());
+                processed.set(block.getId());
+                trace.add(block);
+                unblock(block);
+                block.setLinearScanNumber(blockNumber++);
             }
         }
         return trace;
@@ -120,11 +120,7 @@
 
     private boolean checkPredecessorsProcessed(AbstractBlockBase<?> block) {
         for (AbstractBlockBase<?> pred : block.getPredecessors()) {
-            if (!processed(pred)) {
-                assert false : "Predecessor unscheduled: " + pred;
-                return false;
-            }
-
+            assert processed(pred) : "Predecessor unscheduled: " + pred;
         }
         return true;
     }
@@ -133,8 +129,8 @@
      * Decrease the {@link #blocked} count for all predecessors and add them to the worklist once
      * the count reaches 0.
      */
-    private void unblock(AbstractBlockBase<?> currentBlock) {
-        for (AbstractBlockBase<?> successor : currentBlock.getSuccessors()) {
+    private void unblock(AbstractBlockBase<?> block) {
+        for (AbstractBlockBase<?> successor : block.getSuccessors()) {
             if (!processed(successor)) {
                 int blockCount = --blocked[successor.getId()];
                 assert blockCount >= 0;
@@ -148,11 +144,11 @@
     /**
      * @return The unprocessed predecessor with the highest probability, or {@code null}.
      */
-    private AbstractBlockBase<?> selectNext(AbstractBlockBase<?> currentBlock) {
+    private AbstractBlockBase<?> selectNext(AbstractBlockBase<?> block) {
         AbstractBlockBase<?> next = null;
-        for (AbstractBlockBase<?> succ : currentBlock.getSuccessors()) {
-            if (!processed(succ) && (next == null || succ.probability() > next.probability())) {
-                next = succ;
+        for (AbstractBlockBase<?> successor : block.getSuccessors()) {
+            if (!processed(successor) && (next == null || successor.probability() > next.probability())) {
+                next = successor;
             }
         }
         return next;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/AbstractObjectStamp.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/AbstractObjectStamp.java	Fri Mar 16 22:59:32 2018 -0700
@@ -191,8 +191,6 @@
         boolean joinExactType = exactType || other.exactType;
         if (Objects.equals(type, other.type)) {
             joinType = type;
-        } else if (type == null && other.type == null) {
-            joinType = null;
         } else if (type == null) {
             joinType = other.type;
         } else if (other.type == null) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/FloatStamp.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/FloatStamp.java	Fri Mar 16 22:59:32 2018 -0700
@@ -176,11 +176,15 @@
         StringBuilder str = new StringBuilder();
         str.append('f');
         str.append(getBits());
-        str.append(nonNaN ? "!" : "");
-        if (lowerBound == upperBound) {
-            str.append(" [").append(lowerBound).append(']');
-        } else if (lowerBound != Double.NEGATIVE_INFINITY || upperBound != Double.POSITIVE_INFINITY) {
-            str.append(" [").append(lowerBound).append(" - ").append(upperBound).append(']');
+        if (hasValues()) {
+            str.append(nonNaN ? "!" : "");
+            if (lowerBound == upperBound) {
+                str.append(" [").append(lowerBound).append(']');
+            } else if (lowerBound != Double.NEGATIVE_INFINITY || upperBound != Double.POSITIVE_INFINITY) {
+                str.append(" [").append(lowerBound).append(" - ").append(upperBound).append(']');
+            }
+        } else {
+            str.append("<empty>");
         }
         return str.toString();
     }
@@ -200,6 +204,12 @@
         if (otherStamp == this) {
             return this;
         }
+        if (isEmpty()) {
+            return this;
+        }
+        if (otherStamp.isEmpty()) {
+            return otherStamp;
+        }
         FloatStamp other = (FloatStamp) otherStamp;
         assert getBits() == other.getBits();
         double meetUpperBound = meetBounds(upperBound, other.upperBound, Math::max);
@@ -383,6 +393,9 @@
 
                         @Override
                         public Stamp foldStamp(Stamp s) {
+                            if (s.isEmpty()) {
+                                return s;
+                            }
                             FloatStamp stamp = (FloatStamp) s;
                             Stamp folded = maybeFoldConstant(this, stamp);
                             if (folded != null) {
@@ -412,6 +425,12 @@
 
                         @Override
                         public Stamp foldStamp(Stamp s1, Stamp s2) {
+                            if (s1.isEmpty()) {
+                                return s1;
+                            }
+                            if (s2.isEmpty()) {
+                                return s2;
+                            }
                             FloatStamp stamp1 = (FloatStamp) s1;
                             FloatStamp stamp2 = (FloatStamp) s2;
                             Stamp folded = maybeFoldConstant(this, stamp1, stamp2);
@@ -454,6 +473,12 @@
 
                         @Override
                         public Stamp foldStamp(Stamp s1, Stamp s2) {
+                            if (s1.isEmpty()) {
+                                return s1;
+                            }
+                            if (s2.isEmpty()) {
+                                return s2;
+                            }
                             FloatStamp stamp1 = (FloatStamp) s1;
                             FloatStamp stamp2 = (FloatStamp) s2;
                             Stamp folded = maybeFoldConstant(this, stamp1, stamp2);
@@ -496,6 +521,12 @@
 
                         @Override
                         public Stamp foldStamp(Stamp s1, Stamp s2) {
+                            if (s1.isEmpty()) {
+                                return s1;
+                            }
+                            if (s2.isEmpty()) {
+                                return s2;
+                            }
                             FloatStamp stamp1 = (FloatStamp) s1;
                             FloatStamp stamp2 = (FloatStamp) s2;
                             Stamp folded = maybeFoldConstant(this, stamp1, stamp2);
@@ -544,6 +575,12 @@
 
                         @Override
                         public Stamp foldStamp(Stamp s1, Stamp s2) {
+                            if (s1.isEmpty()) {
+                                return s1;
+                            }
+                            if (s2.isEmpty()) {
+                                return s2;
+                            }
                             FloatStamp stamp1 = (FloatStamp) s1;
                             FloatStamp stamp2 = (FloatStamp) s2;
                             Stamp folded = maybeFoldConstant(this, stamp1, stamp2);
@@ -586,6 +623,12 @@
 
                         @Override
                         public Stamp foldStamp(Stamp s1, Stamp s2) {
+                            if (s1.isEmpty()) {
+                                return s1;
+                            }
+                            if (s2.isEmpty()) {
+                                return s2;
+                            }
                             FloatStamp stamp1 = (FloatStamp) s1;
                             FloatStamp stamp2 = (FloatStamp) s2;
                             Stamp folded = maybeFoldConstant(this, stamp1, stamp2);
@@ -615,6 +658,9 @@
 
                         @Override
                         public Stamp foldStamp(Stamp s) {
+                            if (s.isEmpty()) {
+                                return s;
+                            }
                             FloatStamp stamp = (FloatStamp) s;
                             JavaConstant constant = stamp.asConstant();
                             if (constant != null) {
@@ -653,6 +699,12 @@
 
                         @Override
                         public Stamp foldStamp(Stamp s1, Stamp s2) {
+                            if (s1.isEmpty()) {
+                                return s1;
+                            }
+                            if (s2.isEmpty()) {
+                                return s2;
+                            }
                             FloatStamp stamp1 = (FloatStamp) s1;
                             FloatStamp stamp2 = (FloatStamp) s2;
                             Stamp folded = maybeFoldConstant(this, stamp1, stamp2);
@@ -701,6 +753,12 @@
 
                         @Override
                         public Stamp foldStamp(Stamp s1, Stamp s2) {
+                            if (s1.isEmpty()) {
+                                return s1;
+                            }
+                            if (s2.isEmpty()) {
+                                return s2;
+                            }
                             FloatStamp stamp1 = (FloatStamp) s1;
                             FloatStamp stamp2 = (FloatStamp) s2;
                             Stamp folded = maybeFoldConstant(this, stamp1, stamp2);
@@ -747,6 +805,12 @@
 
                         @Override
                         public Stamp foldStamp(Stamp s1, Stamp s2) {
+                            if (s1.isEmpty()) {
+                                return s1;
+                            }
+                            if (s2.isEmpty()) {
+                                return s2;
+                            }
                             FloatStamp stamp1 = (FloatStamp) s1;
                             FloatStamp stamp2 = (FloatStamp) s2;
                             Stamp folded = maybeFoldConstant(this, stamp1, stamp2);
@@ -789,6 +853,9 @@
 
                         @Override
                         public Stamp foldStamp(Stamp s) {
+                            if (s.isEmpty()) {
+                                return s;
+                            }
                             FloatStamp stamp = (FloatStamp) s;
                             Stamp folded = maybeFoldConstant(this, stamp);
                             if (folded != null) {
@@ -818,6 +885,9 @@
 
                         @Override
                         public Stamp foldStamp(Stamp s) {
+                            if (s.isEmpty()) {
+                                return s;
+                            }
                             FloatStamp stamp = (FloatStamp) s;
                             Stamp folded = maybeFoldConstant(this, stamp);
                             if (folded != null) {
@@ -839,6 +909,9 @@
 
                         @Override
                         public Stamp foldStamp(Stamp stamp) {
+                            if (stamp.isEmpty()) {
+                                return StampFactory.empty(JavaKind.Int);
+                            }
                             FloatStamp floatStamp = (FloatStamp) stamp;
                             assert floatStamp.getBits() == 32;
                             boolean mustHaveZero = !floatStamp.isNonNaN();
@@ -865,6 +938,9 @@
 
                         @Override
                         public Stamp foldStamp(Stamp stamp) {
+                            if (stamp.isEmpty()) {
+                                return StampFactory.empty(JavaKind.Long);
+                            }
                             FloatStamp floatStamp = (FloatStamp) stamp;
                             assert floatStamp.getBits() == 32;
                             boolean mustHaveZero = !floatStamp.isNonNaN();
@@ -891,6 +967,9 @@
 
                         @Override
                         public Stamp foldStamp(Stamp stamp) {
+                            if (stamp.isEmpty()) {
+                                return StampFactory.empty(JavaKind.Int);
+                            }
                             FloatStamp floatStamp = (FloatStamp) stamp;
                             assert floatStamp.getBits() == 64;
                             boolean mustHaveZero = !floatStamp.isNonNaN();
@@ -917,6 +996,9 @@
 
                         @Override
                         public Stamp foldStamp(Stamp stamp) {
+                            if (stamp.isEmpty()) {
+                                return StampFactory.empty(JavaKind.Long);
+                            }
                             FloatStamp floatStamp = (FloatStamp) stamp;
                             assert floatStamp.getBits() == 64;
                             boolean mustHaveZero = !floatStamp.isNonNaN();
@@ -943,6 +1025,9 @@
 
                         @Override
                         public Stamp foldStamp(Stamp stamp) {
+                            if (stamp.isEmpty()) {
+                                return StampFactory.empty(JavaKind.Double);
+                            }
                             FloatStamp floatStamp = (FloatStamp) stamp;
                             assert floatStamp.getBits() == 32;
                             return StampFactory.forFloat(JavaKind.Double, floatStamp.lowerBound(), floatStamp.upperBound(), floatStamp.isNonNaN());
@@ -959,6 +1044,9 @@
 
                         @Override
                         public Stamp foldStamp(Stamp stamp) {
+                            if (stamp.isEmpty()) {
+                                return StampFactory.empty(JavaKind.Float);
+                            }
                             FloatStamp floatStamp = (FloatStamp) stamp;
                             assert floatStamp.getBits() == 64;
                             return StampFactory.forFloat(JavaKind.Float, (float) floatStamp.lowerBound(), (float) floatStamp.upperBound(), floatStamp.isNonNaN());
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java	Fri Mar 16 22:59:32 2018 -0700
@@ -122,11 +122,11 @@
         return new IntegerStamp(bits, lowerBoundTmp, upperBoundTmp, defaultMask & (downMask | boundedDownMask), defaultMask & upMask & boundedUpMask);
     }
 
-    static long significantBit(long bits, long value) {
+    private static long significantBit(long bits, long value) {
         return (value >>> (bits - 1)) & 1;
     }
 
-    static long minValueForMasks(int bits, long downMask, long upMask) {
+    private static long minValueForMasks(int bits, long downMask, long upMask) {
         if (significantBit(bits, upMask) == 0) {
             // Value is always positive. Minimum value always positive.
             assert significantBit(bits, downMask) == 0;
@@ -137,7 +137,7 @@
         }
     }
 
-    static long maxValueForMasks(int bits, long downMask, long upMask) {
+    private static long maxValueForMasks(int bits, long downMask, long upMask) {
         if (significantBit(bits, downMask) == 1) {
             // Value is always negative. Maximum value always negative.
             assert significantBit(bits, upMask) == 1;
@@ -330,6 +330,12 @@
         if (otherStamp == this) {
             return this;
         }
+        if (isEmpty()) {
+            return otherStamp;
+        }
+        if (otherStamp.isEmpty()) {
+            return this;
+        }
         IntegerStamp other = (IntegerStamp) otherStamp;
         return createStamp(other, Math.max(upperBound, other.upperBound), Math.min(lowerBound, other.lowerBound), downMask & other.downMask, upMask | other.upMask);
     }
@@ -413,7 +419,7 @@
         return super.equals(other);
     }
 
-    public static long upMaskFor(int bits, long lowerBound, long upperBound) {
+    private static long upMaskFor(int bits, long lowerBound, long upperBound) {
         long mask = lowerBound | upperBound;
         if (mask == 0) {
             return 0;
@@ -595,6 +601,9 @@
 
                         @Override
                         public Stamp foldStamp(Stamp s) {
+                            if (s.isEmpty()) {
+                                return s;
+                            }
                             IntegerStamp stamp = (IntegerStamp) s;
                             int bits = stamp.getBits();
                             if (stamp.lowerBound == stamp.upperBound) {
@@ -622,6 +631,12 @@
 
                         @Override
                         public Stamp foldStamp(Stamp stamp1, Stamp stamp2) {
+                            if (stamp1.isEmpty()) {
+                                return stamp1;
+                            }
+                            if (stamp2.isEmpty()) {
+                                return stamp2;
+                            }
                             IntegerStamp a = (IntegerStamp) stamp1;
                             IntegerStamp b = (IntegerStamp) stamp2;
 
@@ -715,6 +730,12 @@
 
                         @Override
                         public Stamp foldStamp(Stamp stamp1, Stamp stamp2) {
+                            if (stamp1.isEmpty()) {
+                                return stamp1;
+                            }
+                            if (stamp2.isEmpty()) {
+                                return stamp2;
+                            }
                             IntegerStamp a = (IntegerStamp) stamp1;
                             IntegerStamp b = (IntegerStamp) stamp2;
 
@@ -885,6 +906,12 @@
 
                         @Override
                         public Stamp foldStamp(Stamp stamp1, Stamp stamp2) {
+                            if (stamp1.isEmpty()) {
+                                return stamp1;
+                            }
+                            if (stamp2.isEmpty()) {
+                                return stamp2;
+                            }
                             IntegerStamp a = (IntegerStamp) stamp1;
                             IntegerStamp b = (IntegerStamp) stamp2;
                             JavaKind javaKind = a.getStackKind();
@@ -952,6 +979,12 @@
 
                         @Override
                         public Stamp foldStamp(Stamp stamp1, Stamp stamp2) {
+                            if (stamp1.isEmpty()) {
+                                return stamp1;
+                            }
+                            if (stamp2.isEmpty()) {
+                                return stamp2;
+                            }
                             IntegerStamp a = (IntegerStamp) stamp1;
                             IntegerStamp b = (IntegerStamp) stamp2;
                             JavaKind javaKind = a.getStackKind();
@@ -1046,6 +1079,12 @@
 
                         @Override
                         public Stamp foldStamp(Stamp stamp1, Stamp stamp2) {
+                            if (stamp1.isEmpty()) {
+                                return stamp1;
+                            }
+                            if (stamp2.isEmpty()) {
+                                return stamp2;
+                            }
                             IntegerStamp a = (IntegerStamp) stamp1;
                             IntegerStamp b = (IntegerStamp) stamp2;
                             assert a.getBits() == b.getBits();
@@ -1083,6 +1122,12 @@
 
                         @Override
                         public Stamp foldStamp(Stamp stamp1, Stamp stamp2) {
+                            if (stamp1.isEmpty()) {
+                                return stamp1;
+                            }
+                            if (stamp2.isEmpty()) {
+                                return stamp2;
+                            }
                             IntegerStamp a = (IntegerStamp) stamp1;
                             IntegerStamp b = (IntegerStamp) stamp2;
                             assert a.getBits() == b.getBits();
@@ -1121,6 +1166,9 @@
 
                         @Override
                         public Stamp foldStamp(Stamp stamp) {
+                            if (stamp.isEmpty()) {
+                                return stamp;
+                            }
                             IntegerStamp integerStamp = (IntegerStamp) stamp;
                             int bits = integerStamp.getBits();
                             long defaultMask = CodeUtil.mask(bits);
@@ -1140,6 +1188,12 @@
 
                         @Override
                         public Stamp foldStamp(Stamp stamp1, Stamp stamp2) {
+                            if (stamp1.isEmpty()) {
+                                return stamp1;
+                            }
+                            if (stamp2.isEmpty()) {
+                                return stamp2;
+                            }
                             IntegerStamp a = (IntegerStamp) stamp1;
                             IntegerStamp b = (IntegerStamp) stamp2;
                             assert a.getBits() == b.getBits();
@@ -1167,6 +1221,12 @@
 
                         @Override
                         public Stamp foldStamp(Stamp stamp1, Stamp stamp2) {
+                            if (stamp1.isEmpty()) {
+                                return stamp1;
+                            }
+                            if (stamp2.isEmpty()) {
+                                return stamp2;
+                            }
                             IntegerStamp a = (IntegerStamp) stamp1;
                             IntegerStamp b = (IntegerStamp) stamp2;
                             assert a.getBits() == b.getBits();
@@ -1192,6 +1252,12 @@
 
                         @Override
                         public Stamp foldStamp(Stamp stamp1, Stamp stamp2) {
+                            if (stamp1.isEmpty()) {
+                                return stamp1;
+                            }
+                            if (stamp2.isEmpty()) {
+                                return stamp2;
+                            }
                             IntegerStamp a = (IntegerStamp) stamp1;
                             IntegerStamp b = (IntegerStamp) stamp2;
                             assert a.getBits() == b.getBits();
@@ -1269,8 +1335,7 @@
                                         upMask |= value.upMask() << (i & shiftMask);
                                     }
                                 }
-                                Stamp result = IntegerStamp.stampForMask(bits, downMask, upMask & defaultMask);
-                                return result;
+                                return IntegerStamp.stampForMask(bits, downMask, upMask & defaultMask);
                             }
                             return value.unrestricted();
                         }
@@ -1392,6 +1457,9 @@
 
                         @Override
                         public Stamp foldStamp(Stamp input) {
+                            if (input.isEmpty()) {
+                                return input;
+                            }
                             IntegerStamp stamp = (IntegerStamp) input;
                             int bits = stamp.getBits();
                             if (stamp.lowerBound == stamp.upperBound) {
@@ -1419,6 +1487,9 @@
 
                         @Override
                         public Stamp foldStamp(int inputBits, int resultBits, Stamp input) {
+                            if (input.isEmpty()) {
+                                return StampFactory.forInteger(resultBits).empty();
+                            }
                             IntegerStamp stamp = (IntegerStamp) input;
                             assert inputBits == stamp.getBits();
                             assert inputBits <= resultBits;
@@ -1458,6 +1529,9 @@
 
                         @Override
                         public Stamp foldStamp(int inputBits, int resultBits, Stamp input) {
+                            if (input.isEmpty()) {
+                                return StampFactory.forInteger(resultBits).empty();
+                            }
                             IntegerStamp stamp = (IntegerStamp) input;
                             assert inputBits == stamp.getBits();
                             assert inputBits <= resultBits;
@@ -1487,6 +1561,9 @@
 
                         @Override
                         public Stamp foldStamp(int inputBits, int resultBits, Stamp input) {
+                            if (input.isEmpty()) {
+                                return StampFactory.forInteger(resultBits).empty();
+                            }
                             IntegerStamp stamp = (IntegerStamp) input;
                             assert inputBits == stamp.getBits();
                             assert resultBits <= inputBits;
@@ -1526,6 +1603,9 @@
 
                         @Override
                         public Stamp foldStamp(Stamp input) {
+                            if (input.isEmpty()) {
+                                return StampFactory.empty(JavaKind.Float);
+                            }
                             IntegerStamp stamp = (IntegerStamp) input;
                             assert stamp.getBits() == 32;
                             float lowerBound = stamp.lowerBound();
@@ -1544,6 +1624,9 @@
 
                         @Override
                         public Stamp foldStamp(Stamp input) {
+                            if (input.isEmpty()) {
+                                return StampFactory.empty(JavaKind.Float);
+                            }
                             IntegerStamp stamp = (IntegerStamp) input;
                             assert stamp.getBits() == 64;
                             float lowerBound = stamp.lowerBound();
@@ -1562,6 +1645,9 @@
 
                         @Override
                         public Stamp foldStamp(Stamp input) {
+                            if (input.isEmpty()) {
+                                return StampFactory.empty(JavaKind.Double);
+                            }
                             IntegerStamp stamp = (IntegerStamp) input;
                             assert stamp.getBits() == 32;
                             double lowerBound = stamp.lowerBound();
@@ -1580,6 +1666,9 @@
 
                         @Override
                         public Stamp foldStamp(Stamp input) {
+                            if (input.isEmpty()) {
+                                return StampFactory.empty(JavaKind.Double);
+                            }
                             IntegerStamp stamp = (IntegerStamp) input;
                             assert stamp.getBits() == 64;
                             double lowerBound = stamp.lowerBound();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/StampFactory.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/StampFactory.java	Fri Mar 16 22:59:32 2018 -0700
@@ -161,6 +161,10 @@
         return IntegerStamp.create(bits, CodeUtil.minValue(bits), CodeUtil.maxValue(bits), 0, CodeUtil.mask(bits));
     }
 
+    public static IntegerStamp forUnsignedInteger(int bits) {
+        return forUnsignedInteger(bits, 0, NumUtil.maxValueUnsigned(bits), 0, CodeUtil.mask(bits));
+    }
+
     public static IntegerStamp forUnsignedInteger(int bits, long unsignedLowerBound, long unsignedUpperBound) {
         return forUnsignedInteger(bits, unsignedLowerBound, unsignedUpperBound, 0, CodeUtil.mask(bits));
     }
--- /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/util/UnsignedLong.java	Fri Mar 16 22:59:32 2018 -0700
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2018, 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.util;
+
+public final class UnsignedLong {
+    private final long value;
+
+    public UnsignedLong(long value) {
+        this.value = value;
+    }
+
+    public long asLong() {
+        return value;
+    }
+
+    public boolean equals(long unsignedValue) {
+        return value == unsignedValue;
+    }
+
+    public boolean isLessThan(long unsignedValue) {
+        return Long.compareUnsigned(value, unsignedValue) < 0;
+    }
+
+    public boolean isLessOrEqualTo(long unsignedValue) {
+        return Long.compareUnsigned(value, unsignedValue) <= 0;
+    }
+
+    public UnsignedLong times(long unsignedValue) {
+        if (unsignedValue != 0 && Long.compareUnsigned(value, Long.divideUnsigned(0xffff_ffff_ffff_ffffL, unsignedValue)) > 0) {
+            throw new ArithmeticException();
+        }
+        return new UnsignedLong(value * unsignedValue);
+    }
+
+    public UnsignedLong minus(long unsignedValue) {
+        if (Long.compareUnsigned(value, unsignedValue) < 0) {
+            throw new ArithmeticException();
+        }
+        return new UnsignedLong(value - unsignedValue);
+    }
+
+    public UnsignedLong plus(long unsignedValue) {
+        if (Long.compareUnsigned(0xffff_ffff_ffff_ffffL - unsignedValue, value) < 0) {
+            throw new ArithmeticException();
+        }
+        return new UnsignedLong(value + unsignedValue);
+    }
+
+    public UnsignedLong wrappingPlus(long unsignedValue) {
+        return new UnsignedLong(value + unsignedValue);
+    }
+
+    public UnsignedLong wrappingTimes(long unsignedValue) {
+        return new UnsignedLong(value * unsignedValue);
+    }
+
+    @Override
+    public String toString() {
+        return "UnsignedLong(" + Long.toUnsignedString(value) + ")";
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        UnsignedLong that = (UnsignedLong) o;
+        return value == that.value;
+    }
+
+    @Override
+    public int hashCode() {
+        return Long.hashCode(value);
+    }
+}
--- /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/BasePhaseBinaryGraphTest.java	Fri Mar 16 22:59:32 2018 -0700
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2011, 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.debug.DebugContext;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.phases.BasePhase;
+import org.graalvm.compiler.printer.BinaryGraphPrinter;
+import static org.junit.Assert.assertEquals;
+import org.junit.Before;
+import org.junit.Test;
+
+public class BasePhaseBinaryGraphTest {
+    private MyPhase phase;
+    private BinaryGraphPrinter printer;
+
+    @Before
+    public void createPhase() {
+        phase = new MyPhase();
+    }
+
+    @Before
+    public void createPrinter() throws Exception {
+        printer = new BinaryGraphPrinter(DebugContext.DISABLED, null);
+    }
+
+    @Test
+    public void phaseNameIsRecognizedAsType() {
+        String res = printer.typeName(phase.getName());
+        assertEquals(MyPhase.class.getName(), res);
+    }
+
+    private static final class MyPhase extends BasePhase<Void> {
+        @Override
+        protected void run(StructuredGraph graph, Void context) {
+        }
+
+        @Override
+        protected CharSequence getName() {
+            return super.getName();
+        }
+    }
+}
--- /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/ConditionalNodeTest.java	Fri Mar 16 22:59:32 2018 -0700
@@ -0,0 +1,107 @@
+/*
+ * 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.junit.Test;
+
+public class ConditionalNodeTest extends GraalCompilerTest {
+
+    @SuppressWarnings("unused") private static int sink0;
+    @SuppressWarnings("unused") private static int sink1;
+
+    @Test
+    public void test0() {
+        test("conditionalTest0", 0);
+        test("conditionalTest0", 1);
+    }
+
+    public static int conditionalTest0(int a) {
+        int value;
+        if (a == 1) {
+            value = -1;
+            sink1 = 0;
+        } else {
+            value = 6;
+            sink1 = 1;
+        }
+        sink0 = 1;
+        return Math.max(value, 6);
+    }
+
+    @Test
+    public void test1() {
+        test("conditionalTest1", 0);
+        test("conditionalTest1", 1);
+    }
+
+    public static int conditionalTest1(int a) {
+        int value;
+        if (a == 1) {
+            value = -1;
+            sink1 = 0;
+        } else {
+            value = 6;
+            sink1 = 1;
+        }
+        sink0 = 1;
+        return Math.max(6, value);
+    }
+
+    @Test
+    public void test2() {
+        test("conditionalTest2", 0);
+        test("conditionalTest2", 1);
+    }
+
+    public static int conditionalTest2(int a) {
+        int value;
+        if (a == 1) {
+            value = -1;
+            sink1 = 0;
+        } else {
+            value = 6;
+            sink1 = 1;
+        }
+        sink0 = 1;
+        return Math.min(value, -1);
+    }
+
+    @Test
+    public void test3() {
+        test("conditionalTest3", 0);
+        test("conditionalTest3", 1);
+    }
+
+    public static int conditionalTest3(int a) {
+        int value;
+        if (a == 1) {
+            value = -1;
+            sink1 = 0;
+        } else {
+            value = 6;
+            sink1 = 1;
+        }
+        sink0 = 1;
+        return Math.min(-1, value);
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CountedLoopTest.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CountedLoopTest.java	Fri Mar 16 22:59:32 2018 -0700
@@ -30,6 +30,7 @@
 import org.graalvm.compiler.loop.InductionVariable;
 import org.graalvm.compiler.loop.LoopsData;
 import org.graalvm.compiler.nodeinfo.NodeInfo;
+import org.graalvm.compiler.nodes.ConstantNode;
 import org.graalvm.compiler.nodes.NodeView;
 import org.graalvm.compiler.nodes.StructuredGraph;
 import org.graalvm.compiler.nodes.ValueNode;
@@ -52,25 +53,47 @@
         ValueNode get(InductionVariable iv);
     }
 
+    @FunctionalInterface
+    private interface StaticIVProperty {
+        long get(InductionVariable iv);
+    }
+
+    @FunctionalInterface
+    private interface IVPredicate {
+        boolean test(InductionVariable iv);
+    }
+
     /**
      * Get a property of an induction variable.
-     *
-     * @param property
      */
-    private static int get(IVProperty property, int iv) {
+    private static int get(@SuppressWarnings("unused") IVProperty property, @SuppressWarnings("unused") StaticIVProperty staticProperty, @SuppressWarnings("unused") IVPredicate constantCheck,
+                    int iv) {
+        return iv;
+    }
+
+    private static int get(@SuppressWarnings("unused") IVProperty property, int iv) {
+        return iv;
+    }
+
+    private static long get(@SuppressWarnings("unused") IVProperty property, @SuppressWarnings("unused") StaticIVProperty staticProperty, @SuppressWarnings("unused") IVPredicate constantCheck,
+                    long iv) {
+        return iv;
+    }
+
+    private static long get(@SuppressWarnings("unused") IVProperty property, long iv) {
         return iv;
     }
 
     private static class Result {
-        public int extremum;
-        public int exitValue;
+        public long extremum;
+        public long exitValue;
 
         @Override
         public int hashCode() {
             final int prime = 31;
             int result = 1;
-            result = prime * result + exitValue;
-            result = prime * result + extremum;
+            result = prime * result + Long.hashCode(exitValue);
+            result = prime * result + Long.hashCode(extremum);
             return result;
         }
 
@@ -95,7 +118,7 @@
         Result ret = new Result();
         for (i = start; i < limit; i += inc) {
             GraalDirectives.controlFlowAnchor();
-            ret.extremum = get(InductionVariable::extremumNode, i);
+            ret.extremum = get(InductionVariable::extremumNode, InductionVariable::constantExtremum, InductionVariable::isConstantExtremum, i);
         }
         ret.exitValue = get(InductionVariable::exitValueNode, i);
         return ret;
@@ -103,32 +126,42 @@
 
     @Test
     public void increment1() {
-        test("incrementSnippet", 0, 256, 1);
+        testCounted("incrementSnippet", 0, 256, 1);
     }
 
     @Test
     public void increment2() {
-        test("incrementSnippet", 0, 256, 2);
+        testCounted("incrementSnippet", 0, 256, 2);
     }
 
     @Test
     public void increment3() {
-        test("incrementSnippet", 0, 256, 3);
+        testCounted("incrementSnippet", 0, 256, 3);
     }
 
     @Test
     public void increment4() {
-        test("incrementSnippet", -10, Integer.MAX_VALUE, 1);
+        testCounted("incrementSnippet", -10, 1, Integer.MAX_VALUE);
     }
 
     @Test
     public void increment5() {
-        test("incrementSnippet", 256, 256, 1);
+        testCounted("incrementSnippet", 256, 256, 1);
     }
 
     @Test
     public void increment6() {
-        test("incrementSnippet", 257, 256, 1);
+        testCounted("incrementSnippet", 257, 256, 1);
+    }
+
+    @Test
+    public void increment7() {
+        testCounted("incrementSnippet", -10, Integer.MAX_VALUE, 1);
+    }
+
+    @Test
+    public void increment8() {
+        testCounted("incrementSnippet", -10, Integer.MAX_VALUE - 1, 2);
     }
 
     public static Result incrementEqSnippet(int start, int limit, int step) {
@@ -137,7 +170,7 @@
         Result ret = new Result();
         for (i = start; i <= limit; i += inc) {
             GraalDirectives.controlFlowAnchor();
-            ret.extremum = get(InductionVariable::extremumNode, i);
+            ret.extremum = get(InductionVariable::extremumNode, InductionVariable::constantExtremum, InductionVariable::isConstantExtremum, i);
         }
         ret.exitValue = get(InductionVariable::exitValueNode, i);
         return ret;
@@ -145,32 +178,42 @@
 
     @Test
     public void incrementEq1() {
-        test("incrementEqSnippet", 0, 256, 1);
+        testCounted("incrementEqSnippet", 0, 256, 1);
     }
 
     @Test
     public void incrementEq2() {
-        test("incrementEqSnippet", 0, 256, 2);
+        testCounted("incrementEqSnippet", 0, 256, 2);
     }
 
     @Test
     public void incrementEq3() {
-        test("incrementEqSnippet", 0, 256, 3);
+        testCounted("incrementEqSnippet", 0, 256, 3);
     }
 
     @Test
     public void incrementEq4() {
-        test("incrementEqSnippet", -10, 0, Integer.MAX_VALUE);
+        testCounted("incrementEqSnippet", -10, 0, Integer.MAX_VALUE);
     }
 
     @Test
     public void incrementEq5() {
-        test("incrementEqSnippet", 256, 256, 1);
+        testCounted("incrementEqSnippet", 256, 256, 1);
     }
 
     @Test
     public void incrementEq6() {
-        test("incrementEqSnippet", 257, 256, 1);
+        testCounted("incrementEqSnippet", 257, 256, 1);
+    }
+
+    @Test
+    public void incrementEq7() {
+        testCounted("incrementEqSnippet", -10, Integer.MAX_VALUE - 1, 1);
+    }
+
+    @Test
+    public void incrementEq8() {
+        testCounted("incrementEqSnippet", -10, Integer.MAX_VALUE - 2, 2);
     }
 
     public static Result decrementSnippet(int start, int limit, int step) {
@@ -179,7 +222,7 @@
         Result ret = new Result();
         for (i = start; i > limit; i -= dec) {
             GraalDirectives.controlFlowAnchor();
-            ret.extremum = get(InductionVariable::extremumNode, i);
+            ret.extremum = get(InductionVariable::extremumNode, InductionVariable::constantExtremum, InductionVariable::isConstantExtremum, i);
         }
         ret.exitValue = get(InductionVariable::exitValueNode, i);
         return ret;
@@ -187,17 +230,27 @@
 
     @Test
     public void decrement1() {
-        test("decrementSnippet", 256, 0, 1);
+        testCounted("decrementSnippet", 256, 0, 1);
     }
 
     @Test
     public void decrement2() {
-        test("decrementSnippet", 256, 0, 2);
+        testCounted("decrementSnippet", 256, 0, 2);
     }
 
     @Test
     public void decrement3() {
-        test("decrementSnippet", 256, 0, 3);
+        testCounted("decrementSnippet", 256, 0, 3);
+    }
+
+    @Test
+    public void decrement4() {
+        testCounted("decrementSnippet", Integer.MAX_VALUE, -10, 1);
+    }
+
+    @Test
+    public void decrement5() {
+        testCounted("decrementSnippet", Integer.MAX_VALUE, -10, 2);
     }
 
     public static Result decrementEqSnippet(int start, int limit, int step) {
@@ -206,7 +259,7 @@
         Result ret = new Result();
         for (i = start; i >= limit; i -= dec) {
             GraalDirectives.controlFlowAnchor();
-            ret.extremum = get(InductionVariable::extremumNode, i);
+            ret.extremum = get(InductionVariable::extremumNode, InductionVariable::constantExtremum, InductionVariable::isConstantExtremum, i);
         }
         ret.exitValue = get(InductionVariable::exitValueNode, i);
         return ret;
@@ -214,22 +267,32 @@
 
     @Test
     public void decrementEq1() {
-        test("decrementEqSnippet", 256, 0, 1);
+        testCounted("decrementEqSnippet", 256, 0, 1);
     }
 
     @Test
     public void decrementEq2() {
-        test("decrementEqSnippet", 256, 0, 2);
+        testCounted("decrementEqSnippet", 256, 0, 2);
     }
 
     @Test
     public void decrementEq3() {
-        test("decrementEqSnippet", 256, 0, 3);
+        testCounted("decrementEqSnippet", 256, 0, 3);
     }
 
     @Test
     public void decrementEq4() {
-        test("decrementEqSnippet", -10, 0, Integer.MAX_VALUE);
+        testCounted("decrementEqSnippet", -10, 0, Integer.MAX_VALUE);
+    }
+
+    @Test
+    public void decrementEq5() {
+        testCounted("decrementEqSnippet", Integer.MAX_VALUE, -10, 1);
+    }
+
+    @Test
+    public void decrementEq6() {
+        testCounted("decrementEqSnippet", Integer.MAX_VALUE, -10, 2);
     }
 
     public static Result twoVariablesSnippet() {
@@ -238,7 +301,7 @@
         for (int i = 0; i < 1024; i++) {
             j += 5;
             GraalDirectives.controlFlowAnchor();
-            ret.extremum = get(InductionVariable::extremumNode, j);
+            ret.extremum = get(InductionVariable::extremumNode, InductionVariable::constantExtremum, InductionVariable::isConstantExtremum, j);
         }
         ret.exitValue = get(InductionVariable::exitValueNode, j);
         return ret;
@@ -246,7 +309,83 @@
 
     @Test
     public void testTwoVariables() {
-        test("twoVariablesSnippet");
+        testCounted("twoVariablesSnippet");
+    }
+
+    public static Result incrementNeqSnippet(int limit) {
+        int i;
+        int posLimit = ((limit - 1) & 0xFFFF) + 1; // make sure limit is always strictly positive
+        Result ret = new Result();
+        for (i = 0; i != posLimit; i++) {
+            GraalDirectives.controlFlowAnchor();
+            ret.extremum = get(InductionVariable::extremumNode, InductionVariable::constantExtremum, InductionVariable::isConstantExtremum, i);
+        }
+        ret.exitValue = get(InductionVariable::exitValueNode, i);
+        return ret;
+    }
+
+    @Test
+    public void decrementNeq() {
+        testCounted("decrementNeqSnippet", 256);
+    }
+
+    public static Result decrementNeqSnippet(int limit) {
+        int i;
+        int posLimit = ((limit - 1) & 0xFFFF) + 1; // make sure limit is always strictly positive
+        Result ret = new Result();
+        for (i = posLimit; i != 0; i--) {
+            GraalDirectives.controlFlowAnchor();
+            ret.extremum = get(InductionVariable::extremumNode, InductionVariable::constantExtremum, InductionVariable::isConstantExtremum, i);
+        }
+        ret.exitValue = get(InductionVariable::exitValueNode, i);
+        return ret;
+    }
+
+    @Test
+    public void incrementNeq() {
+        testCounted("incrementNeqSnippet", 256);
+    }
+
+    public static Result incrementLongSnippet(long start, long limit, long step) {
+        long i;
+        long inc = ((step - 1) & 0xFFFF) + 1; // make sure this value is always strictly positive
+        Result ret = new Result();
+        for (i = start; i < limit; i += inc) {
+            GraalDirectives.controlFlowAnchor();
+            ret.extremum = get(InductionVariable::extremumNode, InductionVariable::constantExtremum, InductionVariable::isConstantExtremum, i);
+        }
+        ret.exitValue = get(InductionVariable::exitValueNode, i);
+        return ret;
+    }
+
+    @Test
+    public void incrementLong1() {
+        testCounted("incrementLongSnippet", 0L, 256L, 1L);
+    }
+
+    @Test
+    public void incrementLong2() {
+        testCounted("incrementLongSnippet", 0L, 256L, 2L);
+    }
+
+    @Test
+    public void incrementLong3() {
+        testCounted("incrementLongSnippet", 0L, 256L, 3L);
+    }
+
+    @Test
+    public void incrementLong4() {
+        testCounted("incrementLongSnippet", -10L, 1L, Long.MAX_VALUE);
+    }
+
+    @Test
+    public void incrementLong5() {
+        testCounted("incrementLongSnippet", 256L, 256L, 1L);
+    }
+
+    @Test
+    public void incrementLong6() {
+        testCounted("incrementLongSnippet", 257L, 256L, 1L);
     }
 
     @NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED)
@@ -255,18 +394,31 @@
         public static final NodeClass<IVPropertyNode> TYPE = NodeClass.create(IVPropertyNode.class);
 
         private final IVProperty property;
+        private final StaticIVProperty staticProperty;
+        private final IVPredicate staticCheck;
         @Input private ValueNode iv;
 
-        protected IVPropertyNode(IVProperty property, ValueNode iv) {
+        protected IVPropertyNode(IVProperty property, StaticIVProperty staticProperty, IVPredicate staticCheck, ValueNode iv) {
             super(TYPE, iv.stamp(NodeView.DEFAULT).unrestricted());
             this.property = property;
+            this.staticProperty = staticProperty;
+            this.staticCheck = staticCheck;
             this.iv = iv;
         }
 
         public void rewrite(LoopsData loops) {
             InductionVariable inductionVariable = loops.getInductionVariable(iv);
             assert inductionVariable != null;
-            ValueNode node = property.get(inductionVariable);
+            ValueNode node = null;
+            if (staticCheck != null) {
+                assert staticProperty != null;
+                if (staticCheck.test(inductionVariable)) {
+                    node = ConstantNode.forLong(staticProperty.get(inductionVariable), graph());
+                }
+            }
+            if (node == null) {
+                node = property.get(inductionVariable);
+            }
             replaceAtUsagesAndDelete(node);
         }
 
@@ -279,7 +431,13 @@
     @Override
     protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) {
         Registration r = new Registration(invocationPlugins, CountedLoopTest.class);
-        r.register2("get", IVProperty.class, int.class, new InvocationPlugin() {
+        registerPlugins(r, JavaKind.Int);
+        registerPlugins(r, JavaKind.Long);
+        super.registerInvocationPlugins(invocationPlugins);
+    }
+
+    private void registerPlugins(Registration r, JavaKind ivKind) {
+        r.register2("get", IVProperty.class, ivKind.toJavaClass(), new InvocationPlugin() {
             @Override
             public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg1, ValueNode arg2) {
                 IVProperty property = null;
@@ -287,14 +445,36 @@
                     property = getSnippetReflection().asObject(IVProperty.class, arg1.asJavaConstant());
                 }
                 if (property != null) {
-                    b.addPush(JavaKind.Int, new IVPropertyNode(property, arg2));
+                    b.addPush(ivKind, new IVPropertyNode(property, null, null, arg2));
                     return true;
                 } else {
                     return false;
                 }
             }
         });
-        super.registerInvocationPlugins(invocationPlugins);
+        r.register4("get", IVProperty.class, StaticIVProperty.class, IVPredicate.class, ivKind.toJavaClass(), new InvocationPlugin() {
+            @Override
+            public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg1, ValueNode arg2, ValueNode arg3, ValueNode arg4) {
+                IVProperty property = null;
+                StaticIVProperty staticProperty = null;
+                IVPredicate staticCheck = null;
+                if (arg1.isConstant()) {
+                    property = getSnippetReflection().asObject(IVProperty.class, arg1.asJavaConstant());
+                }
+                if (arg2.isConstant()) {
+                    staticProperty = getSnippetReflection().asObject(StaticIVProperty.class, arg2.asJavaConstant());
+                }
+                if (arg3.isConstant()) {
+                    staticCheck = getSnippetReflection().asObject(IVPredicate.class, arg3.asJavaConstant());
+                }
+                if (property != null && staticProperty != null && staticCheck != null) {
+                    b.addPush(ivKind, new IVPropertyNode(property, staticProperty, staticCheck, arg4));
+                    return true;
+                } else {
+                    return false;
+                }
+            }
+        });
     }
 
     @Override
@@ -308,37 +488,17 @@
         return true;
     }
 
-    public static Result incrementNeqSnippet(int limit) {
-        int i;
-        int posLimit = ((limit - 1) & 0xFFFF) + 1; // make sure limit is always strictly positive
-        Result ret = new Result();
-        for (i = 0; i != posLimit; i++) {
-            GraalDirectives.controlFlowAnchor();
-            ret.extremum = get(InductionVariable::extremumNode, i);
-        }
-        ret.exitValue = get(InductionVariable::exitValueNode, i);
-        return ret;
+    private Object[] argsToBind;
+
+    @Override
+    protected Object[] getArgumentToBind() {
+        return argsToBind;
     }
 
-    @Test
-    public void decrementNeq() {
-        test("decrementNeqSnippet", 256);
-    }
-
-    public static Result decrementNeqSnippet(int limit) {
-        int i;
-        int posLimit = ((limit - 1) & 0xFFFF) + 1; // make sure limit is always strictly positive
-        Result ret = new Result();
-        for (i = posLimit; i != 0; i--) {
-            GraalDirectives.controlFlowAnchor();
-            ret.extremum = get(InductionVariable::extremumNode, i);
-        }
-        ret.exitValue = get(InductionVariable::exitValueNode, i);
-        return ret;
-    }
-
-    @Test
-    public void incrementNeq() {
-        test("incrementNeqSnippet", 256);
+    public void testCounted(String snippetName, Object... args) {
+        test(snippetName, args);
+        argsToBind = args;
+        test(snippetName, args);
+        argsToBind = null;
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java	Fri Mar 16 22:59:32 2018 -0700
@@ -22,6 +22,7 @@
  */
 package org.graalvm.compiler.core.test;
 
+import static java.lang.reflect.Modifier.isStatic;
 import static jdk.vm.ci.runtime.JVMCICompiler.INVOCATION_ENTRY_BCI;
 import static org.graalvm.compiler.nodes.ConstantNode.getConstantNodes;
 import static org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo.DO_NOT_INLINE_NO_EXCEPTION;
@@ -47,6 +48,7 @@
 import java.util.Set;
 import java.util.function.Supplier;
 
+import jdk.vm.ci.meta.JavaConstant;
 import org.graalvm.compiler.api.directives.GraalDirectives;
 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
 import org.graalvm.compiler.api.test.Graal;
@@ -931,7 +933,8 @@
      */
     @SuppressWarnings("try")
     protected InstalledCode getCode(final ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, boolean forceCompile, boolean installAsDefault, OptionValues options) {
-        if (!forceCompile && graph == null) {
+        boolean useCache = !forceCompile && getArgumentToBind() == null;
+        if (useCache && graph == null) {
             InstalledCode cached = cache.get(installedCodeOwner);
             if (cached != null) {
                 if (cached.isValid()) {
@@ -964,7 +967,7 @@
                             throw new GraalError("Could not install code for " + installedCodeOwner.format("%H.%n(%p)"));
                         }
                     } catch (BailoutException e) {
-                        if (retry <= BAILOUT_RETRY_LIMIT && graph == null && !e.isPermanent()) {
+                        if (retry < BAILOUT_RETRY_LIMIT && graph == null && !e.isPermanent()) {
                             // retry (if there is no predefined graph)
                             TTY.println(String.format("Restart compilation %s (%s) due to a non-permanent bailout!", installedCodeOwner, id));
                             continue;
@@ -978,7 +981,7 @@
                 throw debug.handle(e);
             }
 
-            if (!forceCompile) {
+            if (useCache) {
                 cache.put(installedCodeOwner, installedCode);
             }
             return installedCode;
@@ -1243,12 +1246,33 @@
         DebugContext debug = graph.getDebug();
         try (DebugContext.Scope ds = debug.scope("Parsing", javaMethod, graph)) {
             graphBuilderSuite.apply(graph, getDefaultHighTierContext());
+            Object[] args = getArgumentToBind();
+            if (args != null) {
+                bindArguments(graph, args);
+            }
             return graph;
         } catch (Throwable e) {
             throw debug.handle(e);
         }
     }
 
+    protected void bindArguments(StructuredGraph graph, Object[] argsToBind) {
+        ResolvedJavaMethod m = graph.method();
+        Object receiver = isStatic(m.getModifiers()) ? null : this;
+        Object[] args = argsWithReceiver(receiver, argsToBind);
+        JavaType[] parameterTypes = m.toParameterTypes();
+        assert parameterTypes.length == args.length;
+        for (ParameterNode param : graph.getNodes(ParameterNode.TYPE)) {
+            JavaConstant c = getSnippetReflection().forBoxed(parameterTypes[param.index()].getJavaKind(), args[param.index()]);
+            ConstantNode replacement = ConstantNode.forConstant(c, getMetaAccess(), graph);
+            param.replaceAtUsages(replacement);
+        }
+    }
+
+    protected Object[] getArgumentToBind() {
+        return null;
+    }
+
     protected PhaseSuite<HighTierContext> getEagerGraphBuilderSuite() {
         return getCustomGraphBuilderSuite(GraphBuilderConfiguration.getDefault(getDefaultGraphBuilderPlugins()).withEagerResolving(true).withUnresolvedIsError(true));
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphEncoderTest.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphEncoderTest.java	Fri Mar 16 22:59:32 2018 -0700
@@ -77,8 +77,7 @@
         }
 
         for (StructuredGraph originalGraph : originalGraphs) {
-            EncodedGraph encodedGraph = new EncodedGraph(encoder.getEncoding(), startOffsets.get(originalGraph), encoder.getObjects(), encoder.getNodeClasses(), originalGraph.getAssumptions(),
-                            originalGraph.getMethods());
+            EncodedGraph encodedGraph = new EncodedGraph(encoder.getEncoding(), startOffsets.get(originalGraph), encoder.getObjects(), encoder.getNodeClasses(), originalGraph);
             GraphEncoder.verifyEncoding(originalGraph, encodedGraph, getTarget().arch);
         }
     }
--- /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/SwitchDyingLoopTest.java	Fri Mar 16 22:59:32 2018 -0700
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2018, 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 static org.graalvm.compiler.graph.test.matchers.NodeIterableCount.hasCount;
+import static org.graalvm.compiler.graph.test.matchers.NodeIterableIsEmpty.isEmpty;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+
+import org.graalvm.compiler.core.common.type.StampFactory;
+import org.graalvm.compiler.nodes.LoopBeginNode;
+import org.graalvm.compiler.nodes.ParameterNode;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.extended.IntegerSwitchNode;
+import org.graalvm.compiler.phases.common.CanonicalizerPhase;
+import org.graalvm.compiler.phases.tiers.HighTierContext;
+import org.junit.Test;
+
+import jdk.vm.ci.meta.JavaKind;
+
+public class SwitchDyingLoopTest extends GraalCompilerTest {
+
+    @SuppressWarnings("fallthrough")
+    public static int snippet(int a, int n) {
+        int r = 0;
+        loop: for (int i = 0; i < n; i++) {
+            int v = (i * 167 + 13) & 0xff;
+            switch (v & a) {
+                case 0x80:
+                    r += 1; // fall through
+                case 0x40:
+                    r += 2; // fall through
+                case 0x20:
+                    r += 3;
+                    continue;
+                case 0x08:
+                    r += 5; // fall through
+                case 0x04:
+                    r += 7; // fall through
+                case 0x02:
+                    r += 9; // fall through
+                default:
+                    break loop;
+            }
+        }
+        return r;
+    }
+
+    @Test
+    public void test() {
+        CanonicalizerPhase canonicalizerPhase = new CanonicalizerPhase();
+        HighTierContext highTierContext = getDefaultHighTierContext();
+        StructuredGraph graph = parseEager("snippet", StructuredGraph.AllowAssumptions.YES);
+        // there should be 1 loop and 1 switch
+        assertThat(graph.getNodes(LoopBeginNode.TYPE), hasCount(1));
+        assertThat(graph.getNodes(IntegerSwitchNode.TYPE), hasCount(1));
+        canonicalizerPhase.apply(graph, highTierContext);
+        // after canonicalization, the loop and switch should still be there
+        assertThat(graph.getNodes(LoopBeginNode.TYPE), hasCount(1));
+        assertThat(graph.getNodes(IntegerSwitchNode.TYPE), hasCount(1));
+        // add stamp to `a` so that paths leading to continue can be trimmed
+        ParameterNode parameter = graph.getParameter(0);
+        assertNotNull(parameter);
+        parameter.setStamp(StampFactory.forInteger(JavaKind.Int, 0, 255, 0, 0xf));
+        canonicalizerPhase.apply(graph, highTierContext);
+        // the loop should have disappeared and there should still be a switch
+        assertThat(graph.getNodes(LoopBeginNode.TYPE), isEmpty());
+        assertThat(graph.getNodes(IntegerSwitchNode.TYPE), hasCount(1));
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TrivialInliningExplosionTest.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TrivialInliningExplosionTest.java	Fri Mar 16 22:59:32 2018 -0700
@@ -74,9 +74,9 @@
         int afterCompileSize = lastCompiledGraph.getNodeCount();
 
         // The values of afterParseSize and afterCompileSize when this
-        // test was written were 849 and 848 respectively.
-        Assert.assertTrue(afterParseSize < 2000);
-        Assert.assertTrue(afterCompileSize < 2000);
+        // test was written were 3223 and 3505 respectively.
+        Assert.assertTrue(afterParseSize < 4000);
+        Assert.assertTrue(afterCompileSize < 4000);
 
     }
 }
--- /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/UnsignedLongTest.java	Fri Mar 16 22:59:32 2018 -0700
@@ -0,0 +1,139 @@
+/*
+ * 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.core.common.util.UnsignedLong;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class UnsignedLongTest {
+    @Test
+    public void testEquals() {
+        UnsignedLong fortyTwo = new UnsignedLong(42);
+        Assert.assertTrue(fortyTwo.equals(42));
+        Assert.assertFalse(fortyTwo.equals(99));
+        UnsignedLong longFortyTwo = new UnsignedLong(0x42_0000_8888L);
+        Assert.assertTrue(longFortyTwo.equals(0x42_0000_8888L));
+        Assert.assertFalse(longFortyTwo.equals(0x99_0000_8888L));
+        UnsignedLong longUnsigned = new UnsignedLong(0x8000_7777_0000_8888L);
+        Assert.assertTrue(longUnsigned.equals(0x8000_7777_0000_8888L));
+        Assert.assertFalse(longUnsigned.equals(0xf000_7777_0000_8888L));
+    }
+
+    @Test
+    public void testIsLessThan() {
+        UnsignedLong fortyTwo = new UnsignedLong(42);
+        Assert.assertTrue(fortyTwo.isLessThan(45));
+        Assert.assertFalse(fortyTwo.isLessThan(42));
+        Assert.assertFalse(fortyTwo.isLessThan(40));
+        Assert.assertTrue(fortyTwo.isLessThan(0xffff_ffff_ffff_ffffL));
+        UnsignedLong longUnsigned = new UnsignedLong(0x8000_7777_0000_8888L);
+        Assert.assertTrue(longUnsigned.isLessThan(0xffff_ffff_ffff_ffffL));
+        Assert.assertFalse(longUnsigned.isLessThan(42));
+        Assert.assertFalse(longUnsigned.isLessThan(0x8000_0777_0000_8888L));
+        Assert.assertFalse(longUnsigned.isLessThan(0x8000_7777_0000_8888L));
+    }
+
+    @Test
+    public void testIsLessOrEqualTo() {
+        UnsignedLong fortyTwo = new UnsignedLong(42);
+        Assert.assertTrue(fortyTwo.isLessOrEqualTo(45));
+        Assert.assertTrue(fortyTwo.isLessOrEqualTo(42));
+        Assert.assertFalse(fortyTwo.isLessOrEqualTo(40));
+        Assert.assertTrue(fortyTwo.isLessOrEqualTo(0xffff_ffff_ffff_ffffL));
+        UnsignedLong longUnsigned = new UnsignedLong(0x8000_7777_0000_8888L);
+        Assert.assertTrue(longUnsigned.isLessOrEqualTo(0xffff_ffff_ffff_ffffL));
+        Assert.assertFalse(longUnsigned.isLessOrEqualTo(42));
+        Assert.assertFalse(longUnsigned.isLessOrEqualTo(0x8000_0777_0000_8888L));
+        Assert.assertTrue(longUnsigned.isLessOrEqualTo(0x8000_7777_0000_8888L));
+    }
+
+    @Test
+    public void testTimes() {
+        UnsignedLong fortyTwo = new UnsignedLong(42);
+        Assert.assertEquals(42 * 42, fortyTwo.times(42).asLong());
+        Assert.assertEquals(0xffff_ffff_ffff_fff0L, fortyTwo.times(0x618618618618618L).asLong());
+    }
+
+    @Test(expected = ArithmeticException.class)
+    public void testTimesException() {
+        UnsignedLong fortyTwo = new UnsignedLong(42);
+        fortyTwo.times(0x618618618618619L);
+    }
+
+    @Test
+    public void testMinus() {
+        UnsignedLong fortyTwo = new UnsignedLong(42);
+        Assert.assertEquals(0, fortyTwo.minus(42).asLong());
+        Assert.assertEquals(40, fortyTwo.minus(2).asLong());
+        UnsignedLong longUnsigned = new UnsignedLong(0xffff_ffff_ffff_fff0L);
+        Assert.assertEquals(0, longUnsigned.minus(0xffff_ffff_ffff_fff0L).asLong());
+    }
+
+    @Test(expected = ArithmeticException.class)
+    public void testMinusException() {
+        UnsignedLong fortyTwo = new UnsignedLong(42);
+        fortyTwo.minus(43);
+    }
+
+    @Test(expected = ArithmeticException.class)
+    public void testMinusException2() {
+        UnsignedLong longUnsigned = new UnsignedLong(0xffff_ffff_ffff_fff0L);
+        longUnsigned.minus(0xffff_ffff_ffff_fff1L);
+    }
+
+    @Test
+    public void testPlus() {
+        UnsignedLong fortyTwo = new UnsignedLong(42);
+        Assert.assertEquals(84, fortyTwo.plus(42).asLong());
+        Assert.assertEquals(44, fortyTwo.plus(2).asLong());
+        UnsignedLong longUnsigned = new UnsignedLong(0xffff_ffff_ffff_fff0L);
+        Assert.assertEquals(0xffff_ffff_ffff_ffffL, longUnsigned.plus(0xf).asLong());
+    }
+
+    @Test(expected = ArithmeticException.class)
+    public void testPlusException() {
+        UnsignedLong fortyTwo = new UnsignedLong(42);
+        fortyTwo.plus(0xffff_ffff_ffff_fff0L);
+    }
+
+    @Test(expected = ArithmeticException.class)
+    public void testPlusException2() {
+        UnsignedLong longUnsigned = new UnsignedLong(0xffff_ffff_ffff_fff0L);
+        longUnsigned.plus(42);
+    }
+
+    @Test
+    public void testWrappingTimes() {
+        UnsignedLong fortyTwo = new UnsignedLong(42);
+        Assert.assertEquals(0x1a, fortyTwo.wrappingTimes(0x618618618618619L).asLong());
+    }
+
+    @Test
+    public void testWrappingPlus() {
+        UnsignedLong fortyTwo = new UnsignedLong(42);
+        Assert.assertEquals(0x1a, fortyTwo.wrappingPlus(0xffff_ffff_ffff_fff0L).asLong());
+        UnsignedLong longUnsigned = new UnsignedLong(0xffff_ffff_ffff_fff0L);
+        Assert.assertEquals(0x1a, longUnsigned.wrappingPlus(42).asLong());
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java	Fri Mar 16 22:59:32 2018 -0700
@@ -240,6 +240,7 @@
             debug.dump(DebugContext.BASIC_LEVEL, graph, "After low tier");
 
             debug.dump(DebugContext.BASIC_LEVEL, graph.getLastSchedule(), "Final HIR schedule");
+            graph.logInliningTree();
         } catch (Throwable e) {
             throw debug.handle(e);
         } finally {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java	Fri Mar 16 22:59:32 2018 -0700
@@ -316,6 +316,10 @@
         return values.toArray(new Value[values.size()]);
     }
 
+    public void doBlockPrologue(@SuppressWarnings("unused") Block block, @SuppressWarnings("unused") OptionValues options) {
+
+    }
+
     @Override
     @SuppressWarnings("try")
     public void doBlock(Block block, StructuredGraph graph, BlockMap<List<Node>> blockMap) {
@@ -341,6 +345,7 @@
                     }
                 }
             }
+            doBlockPrologue(block, options);
 
             List<Node> nodes = blockMap.get(block);
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/HighTier.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/HighTier.java	Fri Mar 16 22:59:32 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -45,6 +45,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.NodeCounterPhase;
 import org.graalvm.compiler.phases.common.ConvertDeoptimizeToGuardPhase;
 import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase;
 import org.graalvm.compiler.phases.common.IncrementalCanonicalizerPhase;
@@ -74,6 +75,10 @@
 
         appendPhase(canonicalizer);
 
+        if (NodeCounterPhase.Options.NodeCounters.getValue(options)) {
+            appendPhase(new NodeCounterPhase());
+        }
+
         if (Options.Inline.getValue(options)) {
             appendPhase(new InliningPhase(canonicalizer));
             appendPhase(new DeadCodeEliminationPhase(Optional));
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java	Fri Mar 16 22:59:32 2018 -0700
@@ -178,7 +178,7 @@
      * @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 compilation request or {@code null}
-     * @param compilationResult the code to be compiled
+     * @param compilationResult the code to be installed
      * @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.
@@ -204,12 +204,13 @@
         }
         try (DebugContext.Scope s2 = debug.scope("CodeInstall", debugContext);
                         DebugContext.Activation a = debug.activate()) {
-            preCodeInstallationTasks(tasks, compilationResult);
 
             InstalledCode installedCode;
             try {
+                preCodeInstallationTasks(tasks, compilationResult, predefinedInstalledCode);
                 CompiledCode compiledCode = createCompiledCode(method, compilationRequest, compilationResult);
                 installedCode = getProviders().getCodeCache().installCode(method, compiledCode, predefinedInstalledCode, speculationLog, isDefault);
+                assert predefinedInstalledCode == null || installedCode == predefinedInstalledCode;
             } catch (Throwable t) {
                 failCodeInstallationTasks(tasks, t);
                 throw t;
@@ -229,9 +230,9 @@
         }
     }
 
-    private static void preCodeInstallationTasks(CodeInstallationTask[] tasks, CompilationResult compilationResult) {
+    private static void preCodeInstallationTasks(CodeInstallationTask[] tasks, CompilationResult compilationResult, InstalledCode predefinedInstalledCode) {
         for (CodeInstallationTask task : tasks) {
-            task.preProcess(compilationResult);
+            task.preProcess(compilationResult, predefinedInstalledCode);
         }
     }
 
@@ -305,23 +306,29 @@
     public abstract static class CodeInstallationTask {
         /**
          * Task to run before code installation.
+         *
+         * @param compilationResult the code about to be installed
+         * @param predefinedInstalledCode a pre-allocated {@link InstalledCode} object that will be
+         *            used as a reference to the installed code. May be {@code null}.
+         *
          */
-        @SuppressWarnings("unused")
-        public void preProcess(CompilationResult compilationResult) {
+        public void preProcess(CompilationResult compilationResult, InstalledCode predefinedInstalledCode) {
         }
 
         /**
          * Task to run after the code is installed.
+         *
+         * @param installedCode a reference to the installed code
          */
-        @SuppressWarnings("unused")
         public void postProcess(InstalledCode installedCode) {
         }
 
         /**
          * Invoked after {@link #preProcess} when code installation fails.
+         *
+         * @param cause the cause of the installation failure
          */
-        @SuppressWarnings("unused")
-        public void installFailed(Throwable t) {
+        public void installFailed(Throwable cause) {
         }
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/.checkstyle_checks.xml	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/.checkstyle_checks.xml	Fri Mar 16 22:59:32 2018 -0700
@@ -116,7 +116,7 @@
       <metadata name="net.sf.eclipsecs.core.comment" value="Illegal trailing whitespace(s) at the end of the line."/>
       <property name="format" value="\s$"/>
       <property name="message" value="Illegal trailing whitespace(s) at the end of the line."/>
-      <property name="ignoreComments" value="true"/>
+      <property name="ignoreComments" value="false"/>
       <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Checks for trailing spaces at the end of a line"/>
     </module>
     <module name="RegexpSinglelineJava">
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java	Fri Mar 16 22:59:32 2018 -0700
@@ -22,6 +22,9 @@
  */
 package org.graalvm.compiler.graph;
 
+import static org.graalvm.compiler.graph.Graph.SourcePositionTracking.Default;
+import static org.graalvm.compiler.graph.Graph.SourcePositionTracking.Track;
+import static org.graalvm.compiler.graph.Graph.SourcePositionTracking.UpdateOnly;
 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED;
 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED;
 
@@ -33,6 +36,7 @@
 import org.graalvm.collections.EconomicMap;
 import org.graalvm.collections.Equivalence;
 import org.graalvm.collections.UnmodifiableEconomicMap;
+import org.graalvm.compiler.core.common.GraalOptions;
 import org.graalvm.compiler.debug.CounterKey;
 import org.graalvm.compiler.debug.DebugCloseable;
 import org.graalvm.compiler.debug.DebugContext;
@@ -65,6 +69,13 @@
         DeepFreeze
     }
 
+    public enum SourcePositionTracking {
+        Default,
+        Ignore,
+        UpdateOnly,
+        Track
+    }
+
     public final String name;
 
     /**
@@ -80,7 +91,7 @@
     /**
      * Records if updating of node source information is required when performing inlining.
      */
-    boolean seenNodeSourcePosition;
+    protected SourcePositionTracking trackNodeSourcePosition;
 
     /**
      * The number of valid entries in {@link #nodes}.
@@ -195,7 +206,7 @@
      *         was opened
      */
     public DebugCloseable withNodeSourcePosition(NodeSourcePosition sourcePosition) {
-        return sourcePosition != null ? new NodeSourcePositionScope(sourcePosition) : null;
+        return trackNodeSourcePosition() && sourcePosition != null ? new NodeSourcePositionScope(sourcePosition) : null;
     }
 
     /**
@@ -212,16 +223,26 @@
      * to short circuit logic for updating those positions after inlining since that requires
      * visiting every node in the graph.
      */
-    public boolean mayHaveNodeSourcePosition() {
-        assert seenNodeSourcePosition || verifyHasNoSourcePosition();
-        return seenNodeSourcePosition;
+    public boolean updateNodeSourcePosition() {
+        return trackNodeSourcePosition == Track || trackNodeSourcePosition == UpdateOnly;
     }
 
-    private boolean verifyHasNoSourcePosition() {
-        for (Node node : getNodes()) {
-            assert node.getNodeSourcePosition() == null;
+    public boolean trackNodeSourcePosition() {
+        return trackNodeSourcePosition == Track;
+    }
+
+    public void setTrackNodeSourcePosition() {
+        if (trackNodeSourcePosition != Track) {
+            assert trackNodeSourcePosition == Default : trackNodeSourcePosition;
+            trackNodeSourcePosition = Track;
         }
-        return true;
+    }
+
+    public static SourcePositionTracking trackNodeSourcePositionDefault(OptionValues options, DebugContext debug) {
+        if (GraalOptions.TrackNodeSourcePosition.getValue(options) || debug.isDumpEnabledForMethod()) {
+            return Track;
+        }
+        return Default;
     }
 
     /**
@@ -255,6 +276,7 @@
         iterableNodesLast = new ArrayList<>(NodeClass.allocatedNodeIterabledIds());
         this.name = name;
         this.options = options;
+        this.trackNodeSourcePosition = trackNodeSourcePositionDefault(options, debug);
         assert debug != null;
         this.debug = debug;
 
@@ -358,6 +380,9 @@
      */
     protected Graph copy(String newName, Consumer<UnmodifiableEconomicMap<Node, Node>> duplicationMapCallback, DebugContext debugForCopy) {
         Graph copy = new Graph(newName, options, debugForCopy);
+        if (trackNodeSourcePosition()) {
+            copy.setTrackNodeSourcePosition();
+        }
         UnmodifiableEconomicMap<Node, Node> duplicates = copy.addDuplicates(getNodes(), this, this.getNodeCount(), (EconomicMap<Node, Node>) null);
         if (duplicationMapCallback != null) {
             duplicationMapCallback.accept(duplicates);
@@ -1069,10 +1094,9 @@
         int id = nodesSize++;
         nodes[id] = node;
         node.id = id;
-        if (currentNodeSourcePosition != null) {
+        if (currentNodeSourcePosition != null && trackNodeSourcePosition()) {
             node.setNodeSourcePosition(currentNodeSourcePosition);
         }
-        seenNodeSourcePosition = seenNodeSourcePosition || node.getNodeSourcePosition() != null;
 
         updateNodeCaches(node);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/InlineCacheGuardPosition.java	Fri Mar 16 22:59:32 2018 -0700
@@ -0,0 +1,79 @@
+/*
+ * 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.graph;
+
+import java.util.Objects;
+
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+
+public class InlineCacheGuardPosition extends NodeSourcePosition {
+    private final ResolvedJavaType dispatchedType;
+    private final ResolvedJavaMethod concreteMethod;
+    private final int hashCode;
+
+    public InlineCacheGuardPosition(NodeSourcePosition callStack, ResolvedJavaType dispatchedType, ResolvedJavaMethod targetMethod) {
+        super(callStack.getCaller(), callStack.getMethod(), callStack.getBCI());
+        this.concreteMethod = targetMethod;
+        this.dispatchedType = dispatchedType;
+        this.hashCode = super.hashCode() + 7 * ((dispatchedType == null) ? 0 : dispatchedType.hashCode()) + 31 * targetMethod.hashCode();
+    }
+
+    public ResolvedJavaType getDispatchedType() {
+        return dispatchedType;
+    }
+
+    public ResolvedJavaMethod getTargetMethod() {
+        return concreteMethod;
+    }
+
+    @Override
+    public int hashCode() {
+        return hashCode;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (obj != null && getClass() == obj.getClass()) {
+            InlineCacheGuardPosition that = (InlineCacheGuardPosition) obj;
+            if (hashCode != that.hashCode) {
+                return false;
+            }
+            if (this.getBCI() == that.getBCI() && Objects.equals(this.getMethod(), that.getMethod()) && Objects.equals(this.getCaller(), that.getCaller()) &&
+                            Objects.equals(this.concreteMethod, that.concreteMethod) && Objects.equals(this.dispatchedType, that.dispatchedType)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return "dispatchedType=" + (dispatchedType == null ? "null" : dispatchedType.getName()) + " target_method=" + concreteMethod.getName() + " target_method_class=" +
+                        concreteMethod.getDeclaringClass().getName() + " position=" + super.toString();
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java	Fri Mar 16 22:59:32 2018 -0700
@@ -593,10 +593,9 @@
      * Set the source position to {@code sourcePosition}.
      */
     public void setNodeSourcePosition(NodeSourcePosition sourcePosition) {
+        assert sourcePosition != null || this.sourcePosition == null || this.sourcePosition.isPlaceholder() : "Invalid source position at node with id " + id;
         this.sourcePosition = sourcePosition;
-        if (sourcePosition != null && graph != null && !graph.seenNodeSourcePosition) {
-            graph.seenNodeSourcePosition = true;
-        }
+        // assert sourcePosition == null || graph == null || graph.trackNodeSourcePosition;
     }
 
     /**
@@ -920,6 +919,9 @@
         }
         newNode.graph = into;
         newNode.id = INITIAL_ID;
+        if (sourcePosition != null && (into == null || into.updateNodeSourcePosition())) {
+            newNode.setNodeSourcePosition(sourcePosition);
+        }
         if (into != null) {
             into.register(newNode);
         }
@@ -928,9 +930,6 @@
         if (into != null && useIntoLeafNodeCache) {
             into.putNodeIntoCache(newNode);
         }
-        if (graph != null && into != null && sourcePosition != null) {
-            newNode.setNodeSourcePosition(sourcePosition);
-        }
         newNode.afterClone(this);
         return newNode;
     }
@@ -1195,6 +1194,15 @@
         return getNodeClass().dataEquals(this, other);
     }
 
+    /**
+     * Determines if this node is equal to the other node while ignoring differences in
+     * {@linkplain Successor control-flow} edges.
+     *
+     */
+    public boolean dataFlowEquals(Node other) {
+        return this == other || nodeClass == other.getNodeClass() && this.valueEquals(other) && nodeClass.equalInputs(this, other);
+    }
+
     public final void pushInputs(NodeStack stack) {
         getNodeClass().pushInputs(this, stack);
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java	Fri Mar 16 22:59:32 2018 -0700
@@ -104,7 +104,7 @@
      * Gets the {@link NodeClass} associated with a given {@link Class}.
      */
     public static <T> NodeClass<T> create(Class<T> c) {
-        assert get(c) == null;
+        assert getUnchecked(c) == null;
         Class<? super T> superclass = c.getSuperclass();
         NodeClass<? super T> nodeSuperclass = null;
         if (superclass != NODE_CLASS) {
@@ -114,9 +114,9 @@
     }
 
     @SuppressWarnings("unchecked")
-    public static <T> NodeClass<T> get(Class<T> superclass) {
+    private static <T> NodeClass<T> getUnchecked(Class<T> clazz) {
         try {
-            Field field = superclass.getDeclaredField("TYPE");
+            Field field = clazz.getDeclaredField("TYPE");
             field.setAccessible(true);
             return (NodeClass<T>) field.get(null);
         } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) {
@@ -124,6 +124,14 @@
         }
     }
 
+    public static <T> NodeClass<T> get(Class<T> clazz) {
+        NodeClass<T> result = getUnchecked(clazz);
+        if (result == null && clazz != NODE_CLASS) {
+            throw GraalError.shouldNotReachHere("TYPE field not initialized for class " + clazz.getTypeName());
+        }
+        return result;
+    }
+
     private static final Class<?> NODE_CLASS = Node.class;
     private static final Class<?> INPUT_LIST_CLASS = NodeInputList.class;
     private static final Class<?> SUCCESSOR_LIST_CLASS = NodeSuccessorList.class;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeSourcePosition.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeSourcePosition.java	Fri Mar 16 22:59:32 2018 -0700
@@ -22,31 +22,100 @@
  */
 package org.graalvm.compiler.graph;
 
+import static org.graalvm.compiler.graph.NodeSourcePosition.Marker.None;
+import static org.graalvm.compiler.graph.NodeSourcePosition.Marker.Placeholder;
+import static org.graalvm.compiler.graph.NodeSourcePosition.Marker.Substitution;
+
 import java.util.Objects;
 
+import org.graalvm.compiler.bytecode.BytecodeDisassembler;
+import org.graalvm.compiler.bytecode.Bytecodes;
+
+import jdk.vm.ci.code.BytecodeFrame;
 import jdk.vm.ci.code.BytecodePosition;
 import jdk.vm.ci.code.CodeUtil;
-import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaMethod;
 import jdk.vm.ci.meta.MetaUtil;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 
 public class NodeSourcePosition extends BytecodePosition {
 
+    private static final boolean STRICT_SOURCE_POSITION = Boolean.getBoolean("debug.graal.SourcePositionStrictChecks");
+    private static final boolean SOURCE_POSITION_BYTECODES = Boolean.getBoolean("debug.graal.SourcePositionDisassemble");
+
+    private final int hashCode;
+    private final Marker marker;
+    private final SourceLanguagePosition sourceLanguagePosition;
+
     /**
-     * The receiver of the method this frame refers to.
+     * Remove marker frames.
      */
-    private final JavaConstant receiver;
-    private final int hashCode;
+    public NodeSourcePosition trim() {
+        if (marker != None) {
+            return null;
+        }
+        NodeSourcePosition caller = getCaller();
+        if (caller != null) {
+            caller = caller.trim();
+        }
+        if (caller != getCaller()) {
+            return new NodeSourcePosition(caller, getMethod(), getBCI());
+        }
+        return this;
+    }
 
-    public NodeSourcePosition(JavaConstant receiver, NodeSourcePosition caller, ResolvedJavaMethod method, int bci) {
+    enum Marker {
+        None,
+        Placeholder,
+        Substitution
+    }
+
+    public NodeSourcePosition(NodeSourcePosition caller, ResolvedJavaMethod method, int bci) {
+        this(caller, method, bci, None);
+    }
+
+    public NodeSourcePosition(NodeSourcePosition caller, ResolvedJavaMethod method, int bci, Marker marker) {
+        this(null, caller, method, bci, marker);
+
+    }
+
+    public NodeSourcePosition(SourceLanguagePosition sourceLanguagePosition, NodeSourcePosition caller, ResolvedJavaMethod method, int bci) {
+        this(sourceLanguagePosition, caller, method, bci, None);
+    }
+
+    public NodeSourcePosition(SourceLanguagePosition sourceLanguagePosition, NodeSourcePosition caller, ResolvedJavaMethod method, int bci, Marker marker) {
         super(caller, method, bci);
         if (caller == null) {
             this.hashCode = 31 * bci + method.hashCode();
         } else {
             this.hashCode = caller.hashCode * 7 + 31 * bci + method.hashCode();
         }
-        this.receiver = receiver;
-        assert receiver == null || method.getDeclaringClass().isInstance(receiver);
+        this.marker = marker;
+        this.sourceLanguagePosition = sourceLanguagePosition;
+    }
+
+    public static NodeSourcePosition placeholder(ResolvedJavaMethod method) {
+        return new NodeSourcePosition(null, method, BytecodeFrame.INVALID_FRAMESTATE_BCI, Placeholder);
+    }
+
+    public static NodeSourcePosition placeholder(ResolvedJavaMethod method, int bci) {
+        return new NodeSourcePosition(null, method, bci, Placeholder);
+    }
+
+    public boolean isPlaceholder() {
+        return marker == Placeholder;
+    }
+
+    public static NodeSourcePosition substitution(ResolvedJavaMethod method) {
+        return new NodeSourcePosition(null, method, BytecodeFrame.INVALID_FRAMESTATE_BCI, Substitution);
+    }
+
+    public static NodeSourcePosition substitution(NodeSourcePosition caller, ResolvedJavaMethod method, int bci) {
+        return new NodeSourcePosition(caller, method, bci, Substitution);
+    }
+
+    public boolean isSubstitution() {
+        return marker == Substitution;
     }
 
     @Override
@@ -60,7 +129,7 @@
                 return false;
             }
             if (this.getBCI() == that.getBCI() && Objects.equals(this.getMethod(), that.getMethod()) && Objects.equals(this.getCaller(), that.getCaller()) &&
-                            Objects.equals(this.receiver, that.receiver)) {
+                            Objects.equals(this.sourceLanguagePosition, that.sourceLanguagePosition)) {
                 return true;
             }
         }
@@ -72,8 +141,18 @@
         return hashCode;
     }
 
-    public JavaConstant getReceiver() {
-        return receiver;
+    public int depth() {
+        int d = 0;
+        NodeSourcePosition pos = this;
+        while (pos != null) {
+            d++;
+            pos = pos.getCaller();
+        }
+        return d;
+    }
+
+    public SourceLanguagePosition getSourceLanauage() {
+        return sourceLanguagePosition;
     }
 
     @Override
@@ -81,17 +160,29 @@
         return (NodeSourcePosition) super.getCaller();
     }
 
-    public NodeSourcePosition addCaller(JavaConstant newCallerReceiver, NodeSourcePosition link) {
-        if (getCaller() == null) {
-            assert newCallerReceiver == null || receiver == null : "replacing receiver";
-            return new NodeSourcePosition(newCallerReceiver, link, getMethod(), getBCI());
-        } else {
-            return new NodeSourcePosition(receiver, getCaller().addCaller(newCallerReceiver, link), getMethod(), getBCI());
-        }
+    public NodeSourcePosition addCaller(SourceLanguagePosition newSourceLanguagePosition, NodeSourcePosition link) {
+        return addCaller(newSourceLanguagePosition, link, false);
     }
 
     public NodeSourcePosition addCaller(NodeSourcePosition link) {
-        return addCaller(null, link);
+        return addCaller(null, link, false);
+    }
+
+    public NodeSourcePosition addCaller(NodeSourcePosition link, boolean isSubstitution) {
+        return addCaller(null, link, isSubstitution);
+    }
+
+    public NodeSourcePosition addCaller(SourceLanguagePosition newSourceLanguagePosition, NodeSourcePosition link, boolean isSubstitution) {
+        if (getCaller() == null) {
+            if (isPlaceholder()) {
+                return new NodeSourcePosition(newSourceLanguagePosition, link, getMethod(), 0);
+            }
+            assert link == null || isSubstitution || verifyCaller(this, link) : link;
+
+            return new NodeSourcePosition(newSourceLanguagePosition, link, getMethod(), getBCI());
+        } else {
+            return new NodeSourcePosition(getCaller().addCaller(newSourceLanguagePosition, link, isSubstitution), getMethod(), getBCI());
+        }
     }
 
     @Override
@@ -99,9 +190,9 @@
         StringBuilder sb = new StringBuilder(100);
         NodeSourcePosition pos = this;
         while (pos != null) {
-            MetaUtil.appendLocation(sb.append("at "), pos.getMethod(), pos.getBCI());
-            if (pos.receiver != null) {
-                sb.append("receiver=" + pos.receiver + " ");
+            format(sb, pos);
+            if (pos.sourceLanguagePosition != null) {
+                sb.append(" source=" + pos.sourceLanguagePosition.toShortString());
             }
             pos = pos.getCaller();
             if (pos != null) {
@@ -110,4 +201,55 @@
         }
         return sb.toString();
     }
+
+    private static void format(StringBuilder sb, NodeSourcePosition pos) {
+        MetaUtil.appendLocation(sb.append("at "), pos.getMethod(), pos.getBCI());
+        if (SOURCE_POSITION_BYTECODES) {
+            String disassembly = BytecodeDisassembler.disassembleOne(pos.getMethod(), pos.getBCI());
+            if (disassembly != null && disassembly.length() > 0) {
+                sb.append(" // ");
+                sb.append(disassembly);
+            }
+        }
+    }
+
+    String shallowToString() {
+        StringBuilder sb = new StringBuilder(100);
+        format(sb, this);
+        return sb.toString();
+    }
+
+    public boolean verify() {
+        NodeSourcePosition current = this;
+        NodeSourcePosition caller = getCaller();
+        while (caller != null) {
+            assert verifyCaller(current, caller) : current;
+            current = caller;
+            caller = caller.getCaller();
+        }
+        return true;
+    }
+
+    private static boolean verifyCaller(NodeSourcePosition current, NodeSourcePosition caller) {
+        if (!STRICT_SOURCE_POSITION) {
+            return true;
+        }
+        if (BytecodeFrame.isPlaceholderBci(caller.getBCI())) {
+            return true;
+        }
+        int opcode = BytecodeDisassembler.getBytecodeAt(caller.getMethod(), caller.getBCI());
+        JavaMethod method = BytecodeDisassembler.getInvokedMethodAt(caller.getMethod(), caller.getBCI());
+        /*
+         * It's not really possible to match the declaring classes since this might be an interface
+         * invoke. Matching name and signature probably provides enough accuracy.
+         */
+        assert method == null || (method.getName().equals(current.getMethod().getName()) &&
+                        method.getSignature().equals(current.getMethod().getSignature())) ||
+                        caller.getMethod().getName().equals("linkToTargetMethod") ||
+                        opcode == Bytecodes.INVOKEDYNAMIC ||
+                        caller.getMethod().getDeclaringClass().getName().startsWith("Ljava/lang/invoke/LambdaForm$") ||
+                        current.getMethod().getName().equals("callInlined") : "expected " + method + " but found " +
+                                        current.getMethod();
+        return true;
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/SourceLanguagePosition.java	Fri Mar 16 22:59:32 2018 -0700
@@ -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.graph;
+
+import java.util.Map;
+
+/**
+ * Provides a path to report information about a high level language source position to the Graph
+ * Visualizer.
+ */
+public interface SourceLanguagePosition {
+
+    /**
+     * This is called during dumping of Nodes. The implementation should add any properties which
+     * describe this source position. The actual keys and values used are a private contract between
+     * the language implementation and the Graph Visualizer.
+     */
+    void addSourceInformation(Map<String, Object> props);
+
+    /**
+     * Produce a compact description of this position suitable for printing.
+     */
+    String toShortString();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/SourceLanguagePositionProvider.java	Fri Mar 16 22:59:32 2018 -0700
@@ -0,0 +1,32 @@
+/*
+ * 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.graph;
+
+import jdk.vm.ci.meta.JavaConstant;
+
+/**
+ * Provider of {@link SourceLanguagePosition} for a constant if it represents an AST node.
+ */
+public interface SourceLanguagePositionProvider {
+    SourceLanguagePosition getPosition(JavaConstant node);
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java	Fri Mar 16 22:59:32 2018 -0700
@@ -288,33 +288,37 @@
     }
 
     private static void emitCodeBody(CompilationResultBuilder crb, LIR lir, AArch64MacroAssembler masm) {
-        /*
-         * Insert a nop at the start of the prolog so we can patch in a branch if we need to
-         * invalidate the method later.
-         */
+        emitInvalidatePlaceholder(crb, masm);
+        crb.emit(lir);
+    }
+
+    /**
+     * Insert a nop at the start of the prolog so we can patch in a branch if we need to invalidate
+     * the method later.
+     *
+     * @see "http://mail.openjdk.java.net/pipermail/aarch64-port-dev/2013-September/000273.html"
+     */
+    public static void emitInvalidatePlaceholder(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
         crb.blockComment("[nop for method invalidation]");
         masm.nop();
-
-        crb.emit(lir);
     }
 
     private void emitCodeSuffix(CompilationResultBuilder crb, AArch64MacroAssembler masm, FrameMap frameMap) {
         HotSpotProviders providers = getProviders();
         HotSpotFrameContext frameContext = (HotSpotFrameContext) crb.frameContext;
         if (!frameContext.isStub) {
+            HotSpotForeignCallsProvider foreignCalls = providers.getForeignCalls();
             try (ScratchRegister sc = masm.getScratchRegister()) {
                 Register scratch = sc.getRegister();
-                HotSpotForeignCallsProvider foreignCalls = providers.getForeignCalls();
                 crb.recordMark(config.MARKID_EXCEPTION_HANDLER_ENTRY);
                 ForeignCallLinkage linkage = foreignCalls.lookupForeignCall(EXCEPTION_HANDLER);
                 Register helper = AArch64Call.isNearCall(linkage) ? null : scratch;
                 AArch64Call.directCall(crb, masm, linkage, helper, null);
-
-                crb.recordMark(config.MARKID_DEOPT_HANDLER_ENTRY);
-                linkage = foreignCalls.lookupForeignCall(DEOPTIMIZATION_HANDLER);
-                helper = AArch64Call.isNearCall(linkage) ? null : scratch;
-                AArch64Call.directCall(crb, masm, linkage, helper, null);
             }
+            crb.recordMark(config.MARKID_DEOPT_HANDLER_ENTRY);
+            ForeignCallLinkage linkage = foreignCalls.lookupForeignCall(DEOPTIMIZATION_HANDLER);
+            masm.adr(lr, 0); // Warning: the argument is an offset from the instruction!
+            AArch64Call.directJmp(crb, masm, linkage);
         } else {
             // No need to emit the stubs for entries back into the method since
             // it has no calls that can cause such "return" entries
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotDeoptimizeOp.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotDeoptimizeOp.java	Fri Mar 16 22:59:32 2018 -0700
@@ -46,7 +46,9 @@
 
     @Override
     public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
-        AArch64Call.directCall(crb, masm, crb.foreignCalls.lookupForeignCall(UNCOMMON_TRAP_HANDLER), null, info);
+        try (AArch64MacroAssembler.ScratchRegister scratch = masm.getScratchRegister()) {
+            AArch64Call.directCall(crb, masm, crb.foreignCalls.lookupForeignCall(UNCOMMON_TRAP_HANDLER), scratch.getRegister(), info, null);
+        }
     }
 
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMove.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMove.java	Fri Mar 16 22:59:32 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -155,22 +155,24 @@
 
         @Override
         public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
-            Register ptr = asRegister(input);
+            Register inputRegister = asRegister(input);
             Register resultRegister = asRegister(result);
-            Register base = (isRegister(baseRegister) ? asRegister(baseRegister) : zr);
+            Register base = encoding.hasBase() ? asRegister(baseRegister) : null;
+            emitUncompressCode(masm, inputRegister, resultRegister, base, encoding.getShift(), nonNull);
+        }
+
+        public static void emitUncompressCode(AArch64MacroAssembler masm, Register inputRegister, Register resReg, Register baseReg, int shift, boolean nonNull) {
             // result = base + (ptr << shift)
-            if (nonNull) {
-                masm.add(64, resultRegister, base, ptr, AArch64Assembler.ShiftType.LSL, encoding.getShift());
-            } else if (!encoding.hasBase()) {
-                masm.add(64, resultRegister, zr, ptr, AArch64Assembler.ShiftType.LSL, encoding.getShift());
+            if (nonNull || baseReg == null) {
+                masm.add(64, resReg, baseReg == null ? zr : baseReg, inputRegister, AArch64Assembler.ShiftType.LSL, shift);
             } else {
                 // if ptr is null it has to be null after decompression
                 Label done = new Label();
-                if (!resultRegister.equals(ptr)) {
-                    masm.mov(32, resultRegister, ptr);
+                if (!resReg.equals(inputRegister)) {
+                    masm.mov(32, resReg, inputRegister);
                 }
-                masm.cbz(32, resultRegister, done);
-                masm.add(64, resultRegister, base, resultRegister, AArch64Assembler.ShiftType.LSL, encoding.getShift());
+                masm.cbz(32, resReg, done);
+                masm.add(64, resReg, baseReg, resReg, AArch64Assembler.ShiftType.LSL, shift);
                 masm.bind(done);
             }
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/StubAVXTest.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/StubAVXTest.java	Fri Mar 16 22:59:32 2018 -0700
@@ -65,6 +65,7 @@
 import jdk.vm.ci.meta.MetaAccessProvider;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 import jdk.vm.ci.meta.Value;
+import org.graalvm.compiler.hotspot.HotSpotBackend;
 
 public class StubAVXTest extends LIRTest {
 
@@ -72,6 +73,10 @@
     public void checkAMD64() {
         Assume.assumeTrue("skipping AMD64 specific test", getTarget().arch instanceof AMD64);
         Assume.assumeTrue("skipping AVX test", ((AMD64) getTarget().arch).getFeatures().contains(CPUFeature.AVX));
+        if (getBackend() instanceof HotSpotBackend) {
+            HotSpotBackend backend = (HotSpotBackend) getBackend();
+            Assume.assumeTrue("skipping because of MaxVectorSize", backend.getRuntime().getVMConfig().maxVectorSize >= 32);
+        }
     }
 
     private static final DataPointerConstant avxConstant = new ArrayDataPointerConstant(new float[]{1f, 2f, 3f, 4f, 5f, 6f, 7f, 8f}, 32);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java	Fri Mar 16 22:59:32 2018 -0700
@@ -204,7 +204,7 @@
 
                         if (init >= 0 && extremum >= 0) {
                             long shortestTrip = (extremum - init) / stride + 1;
-                            if (shortestTrip == countedLoopInfo.constantMaxTripCount()) {
+                            if (countedLoopInfo.constantMaxTripCount().equals(shortestTrip)) {
                                 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/AMD64HotSpotArithmeticLIRGenerator.java	Fri Mar 16 11:26:05 2018 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package 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.lir.Variable;
-
-import jdk.vm.ci.meta.Value;
-
-public class AMD64HotSpotArithmeticLIRGenerator extends AMD64ArithmeticLIRGenerator {
-
-    @Override
-    public Value emitMathLog(Value input, boolean base10) {
-        if (GraalArithmeticStubs.getValue(getOptions())) {
-            return super.emitMathLog(input, base10);
-        }
-        Variable result = getLIRGen().newVariable(LIRKind.combine(input));
-        getLIRGen().append(new AMD64HotSpotMathIntrinsicOp(base10 ? LOG10 : LOG, result, getLIRGen().asAllocatable(input)));
-        return result;
-    }
-
-    @Override
-    public Value emitMathCos(Value input) {
-        if (GraalArithmeticStubs.getValue(getOptions())) {
-            return super.emitMathCos(input);
-        }
-        Variable result = getLIRGen().newVariable(LIRKind.combine(input));
-        getLIRGen().append(new AMD64HotSpotMathIntrinsicOp(COS, result, getLIRGen().asAllocatable(input)));
-        return result;
-    }
-
-    @Override
-    public Value emitMathSin(Value input) {
-        if (GraalArithmeticStubs.getValue(getOptions())) {
-            return super.emitMathSin(input);
-        }
-        Variable result = getLIRGen().newVariable(LIRKind.combine(input));
-        getLIRGen().append(new AMD64HotSpotMathIntrinsicOp(SIN, result, getLIRGen().asAllocatable(input)));
-        return result;
-    }
-
-    @Override
-    public Value emitMathTan(Value input) {
-        if (GraalArithmeticStubs.getValue(getOptions())) {
-            return super.emitMathTan(input);
-        }
-        Variable result = getLIRGen().newVariable(LIRKind.combine(input));
-        getLIRGen().append(new AMD64HotSpotMathIntrinsicOp(TAN, result, getLIRGen().asAllocatable(input)));
-        return result;
-    }
-
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Fri Mar 16 22:59:32 2018 -0700
@@ -25,13 +25,13 @@
 import static jdk.vm.ci.amd64.AMD64.rbp;
 import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
 import static org.graalvm.compiler.hotspot.HotSpotBackend.INITIALIZE_KLASS_BY_SYMBOL;
+import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_DYNAMIC_INVOKE;
 import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_KLASS_BY_SYMBOL;
 import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_METHOD_BY_SYMBOL_AND_LOAD_COUNTERS;
 import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_STRING_BY_SYMBOL;
-import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_DYNAMIC_INVOKE;
-import static org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction.RESOLVE;
 import static org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction.INITIALIZE;
 import static org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction.LOAD_COUNTERS;
+import static org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction.RESOLVE;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -115,7 +115,7 @@
     }
 
     private AMD64HotSpotLIRGenerator(HotSpotProviders providers, GraalHotSpotVMConfig config, LIRGenerationResult lirGenRes, BackupSlotProvider backupSlotProvider) {
-        this(new AMD64HotSpotLIRKindTool(), new AMD64HotSpotArithmeticLIRGenerator(), new AMD64HotSpotMoveFactory(backupSlotProvider), providers, config, lirGenRes);
+        this(new AMD64HotSpotLIRKindTool(), new AMD64ArithmeticLIRGenerator(new AMD64HotSpotMaths()), new AMD64HotSpotMoveFactory(backupSlotProvider), providers, config, lirGenRes);
     }
 
     protected AMD64HotSpotLIRGenerator(LIRKindTool lirKindTool, AMD64ArithmeticLIRGenerator arithmeticLIRGen, MoveFactory moveFactory, HotSpotProviders providers, GraalHotSpotVMConfig config,
--- /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/AMD64HotSpotMaths.java	Fri Mar 16 22:59:32 2018 -0700
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+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.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotMove.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotMove.java	Fri Mar 16 22:59:32 2018 -0700
@@ -187,21 +187,26 @@
         public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
             Register inputRegister = asRegister(input);
             Register resReg = asRegister(result);
+            Register baseReg = encoding.hasBase() ? asRegister(baseRegister) : null;
+            emitUncompressCode(masm, inputRegister, resReg, baseReg, encoding.getShift(), nonNull);
+        }
+
+        public static void emitUncompressCode(SPARCMacroAssembler masm, Register inputRegister, Register resReg, Register baseReg, int shift, boolean nonNull) {
             Register secondaryInput;
-            if (encoding.getShift() != 0) {
-                masm.sll(inputRegister, encoding.getShift(), resReg);
+            if (shift != 0) {
+                masm.sll(inputRegister, shift, resReg);
                 secondaryInput = resReg;
             } else {
                 secondaryInput = inputRegister;
             }
 
-            if (encoding.hasBase()) {
+            if (baseReg != null) {
                 if (nonNull) {
-                    masm.add(secondaryInput, asRegister(baseRegister), resReg);
+                    masm.add(secondaryInput, baseReg, resReg);
                 } else {
                     Label done = new Label();
                     BPR.emit(masm, Rc_z, ANNUL, PREDICT_TAKEN, secondaryInput, done);
-                    masm.add(asRegister(baseRegister), secondaryInput, resReg);
+                    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/CompileTheWorld.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java	Fri Mar 16 22:59:32 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -553,6 +553,7 @@
                     classFileCounter++;
 
                     if (className.startsWith("jdk.management.") ||
+                                    className.startsWith("jdk.internal.cmm.*") ||
                                     // GR-5881: The class initializer for
                                     // sun.tools.jconsole.OutputViewer
                                     // spawns non-daemon threads for redirecting sysout and syserr.
--- /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/HotSpotLazyInitializationTest.java	Fri Mar 16 22:59:32 2018 -0700
@@ -0,0 +1,75 @@
+/*
+ * 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.test;
+
+import org.graalvm.compiler.core.test.GraalCompilerTest;
+import org.graalvm.compiler.hotspot.meta.HotSpotClassInitializationPlugin;
+import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Test;
+
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
+public class HotSpotLazyInitializationTest extends GraalCompilerTest {
+
+    HotSpotClassInitializationPlugin classInitPlugin = new HotSpotClassInitializationPlugin();
+
+    @Override
+    protected Plugins getDefaultGraphBuilderPlugins() {
+        Plugins plugins = super.getDefaultGraphBuilderPlugins();
+        plugins.setClassInitializationPlugin(classInitPlugin);
+        return plugins;
+    }
+
+    static boolean initializerRun = false;
+
+    static class X {
+        static {
+            initializerRun = true;
+        }
+
+        static void foo() {
+        }
+    }
+
+    public static void invokeStatic() {
+        X.foo();
+    }
+
+    // If constant pool can do eager resolve without eager initialization, then fail if the compiler
+    // causes the static initializer to run.
+    private void test(String name) {
+        ResolvedJavaMethod method = getResolvedJavaMethod(name);
+        Assume.assumeTrue("skipping for old JVMCI", classInitPlugin.supportsLazyInitialization(method.getConstantPool()));
+        parseEager(method, AllowAssumptions.NO);
+        Assert.assertFalse(initializerRun);
+    }
+
+    @Test
+    public void test1() {
+        test("invokeStatic");
+    }
+
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java	Fri Mar 16 22:59:32 2018 -0700
@@ -24,17 +24,25 @@
 
 import static jdk.vm.ci.common.InitTimer.timer;
 
+import java.net.URL;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.stream.Collectors;
 
 import org.graalvm.collections.EconomicMap;
 import org.graalvm.compiler.debug.GraalError;
+import org.graalvm.compiler.debug.TTY;
+import org.graalvm.compiler.lir.phases.LIRPhase;
+import org.graalvm.compiler.lir.phases.LIRPhaseSuite;
+import org.graalvm.compiler.options.EnumOptionKey;
 import org.graalvm.compiler.options.Option;
 import org.graalvm.compiler.options.OptionKey;
 import org.graalvm.compiler.options.OptionType;
 import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.phases.BasePhase;
+import org.graalvm.compiler.phases.PhaseSuite;
 import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
 import org.graalvm.compiler.serviceprovider.GraalServices;
 
@@ -48,12 +56,20 @@
  */
 public abstract class CompilerConfigurationFactory implements Comparable<CompilerConfigurationFactory> {
 
+    enum ShowConfigurationLevel {
+        none,
+        info,
+        verbose
+    }
+
     static class Options {
         // @formatter:off
         @Option(help = "Names the Graal compiler configuration to use. If ommitted, the compiler configuration " +
                        "with the highest auto-selection priority is used. To see the set of available configurations, " +
                        "supply the value 'help' to this option.", type = OptionType.Expert)
         public static final OptionKey<String> CompilerConfiguration = new OptionKey<>(null);
+        @Option(help = "Writes to the VM log information about the Graal compiler configuration selected.", type = OptionType.User)
+        public static final OptionKey<ShowConfigurationLevel> ShowConfiguration = new EnumOptionKey<>(ShowConfigurationLevel.none);
         // @formatter:on
     }
 
@@ -192,6 +208,52 @@
                 factory = candidates.get(0);
             }
         }
+        ShowConfigurationLevel level = Options.ShowConfiguration.getValue(options);
+        if (level != ShowConfigurationLevel.none) {
+            switch (level) {
+                case info: {
+                    printConfigInfo(factory);
+                    break;
+                }
+                case verbose: {
+                    printConfigInfo(factory);
+                    CompilerConfiguration config = factory.createCompilerConfiguration();
+                    TTY.println("High tier: " + phaseNames(config.createHighTier(options)));
+                    TTY.println("Mid tier: " + phaseNames(config.createMidTier(options)));
+                    TTY.println("Low tier: " + phaseNames(config.createLowTier(options)));
+                    TTY.println("Pre regalloc stage: " + phaseNames(config.createPreAllocationOptimizationStage(options)));
+                    TTY.println("Regalloc stage: " + phaseNames(config.createAllocationStage(options)));
+                    TTY.println("Post regalloc stage: " + phaseNames(config.createPostAllocationOptimizationStage(options)));
+                    config.createAllocationStage(options);
+                    break;
+                }
+            }
+        }
         return factory;
     }
+
+    private static void printConfigInfo(CompilerConfigurationFactory factory) {
+        URL location = factory.getClass().getResource(factory.getClass().getSimpleName() + ".class");
+        TTY.printf("Using Graal compiler configuration '%s' provided by %s loaded from %s%n", factory.name, factory.getClass().getName(), location);
+    }
+
+    private static <C> List<String> phaseNames(PhaseSuite<C> suite) {
+        Collection<BasePhase<? super C>> phases = suite.getPhases();
+        List<String> res = new ArrayList<>(phases.size());
+        for (BasePhase<?> phase : phases) {
+            res.add(phase.contractorName());
+        }
+        Collections.sort(res);
+        return res;
+    }
+
+    private static <C> List<String> phaseNames(LIRPhaseSuite<C> suite) {
+        List<LIRPhase<C>> phases = suite.getPhases();
+        List<String> res = new ArrayList<>(phases.size());
+        for (LIRPhase<?> phase : phases) {
+            res.add(phase.getClass().getName());
+        }
+        Collections.sort(res);
+        return res;
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java	Fri Mar 16 22:59:32 2018 -0700
@@ -45,8 +45,9 @@
      */
     public static final GraalHotSpotVMConfig INJECTED_VMCONFIG = null;
 
+    // this uses `1.9` which will give the correct result with `1.9`, `9`, `10` etc.
     private final boolean isJDK8 = System.getProperty("java.specification.version").compareTo("1.9") < 0;
-    private final int JDKVersion = isJDK8 ? 8 : Integer.parseInt(System.getProperty("java.specification.version"));
+    private final int jdkVersion = isJDK8 ? 8 : Integer.parseInt(System.getProperty("java.specification.version"));
     public final String osName = getHostOSName();
     public final String osArch = getHostArchitectureName();
     public final boolean windowsOs = System.getProperty("os.name", "").startsWith("Windows");
@@ -160,6 +161,7 @@
     public final boolean forceUnreachable = getFlag("ForceUnreachable", Boolean.class);
     public final int codeSegmentSize = getFlag("CodeCacheSegmentSize", Integer.class);
     public final boolean foldStableValues = getFlag("FoldStableValues", Boolean.class);
+    public final int maxVectorSize = getFlag("MaxVectorSize", Integer.class);
 
     public final boolean useTLAB = getFlag("UseTLAB", Boolean.class);
     public final boolean useBiasedLocking = getFlag("UseBiasedLocking", Boolean.class);
@@ -555,12 +557,10 @@
 
     public final int logOfHRGrainBytes = getFieldValue("HeapRegion::LogOfHRGrainBytes", Integer.class, "int");
 
-    public final byte dirtyCardValue = JDKVersion >= 11 ? getConstant("CardTable::dirty_card", Byte.class) :
-                                         (JDKVersion > 8 ? getConstant("CardTableModRefBS::dirty_card", Byte.class) :
-                                         getFieldValue("CompilerToVM::Data::dirty_card", Byte.class, "int"));
-    public final byte g1YoungCardValue = JDKVersion >= 11 ? getConstant("G1CardTable::g1_young_gen", Byte.class) :
-                                           (JDKVersion > 8 ? getConstant("G1SATBCardTableModRefBS::g1_young_gen", Byte.class) :
-                                           getFieldValue("CompilerToVM::Data::g1_young_card", Byte.class, "int"));
+    public final byte dirtyCardValue = jdkVersion >= 11 ? getConstant("CardTable::dirty_card", Byte.class)
+                    : (jdkVersion > 8 ? getConstant("CardTableModRefBS::dirty_card", Byte.class) : getFieldValue("CompilerToVM::Data::dirty_card", Byte.class, "int"));
+    public final byte g1YoungCardValue = jdkVersion >= 11 ? getConstant("G1CardTable::g1_young_gen", Byte.class)
+                    : (jdkVersion > 8 ? getConstant("G1SATBCardTableModRefBS::g1_young_gen", Byte.class) : getFieldValue("CompilerToVM::Data::g1_young_card", Byte.class, "int"));
 
     public final long cardtableStartAddress = getFieldValue("CompilerToVM::Data::cardtable_start_address", Long.class, "jbyte*");
     public final int cardtableShift = getFieldValue("CompilerToVM::Data::cardtable_shift", Integer.class, "int");
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java	Fri Mar 16 22:59:32 2018 -0700
@@ -91,7 +91,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<>(true);
+        public static final OptionKey<Boolean> GraalArithmeticStubs = new OptionKey<>(false); // GR-8276
         @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);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java	Fri Mar 16 22:59:32 2018 -0700
@@ -22,6 +22,8 @@
  */
 package org.graalvm.compiler.hotspot;
 
+import static org.graalvm.util.CollectionsUtil.anyMatch;
+
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.util.ArrayList;
@@ -37,9 +39,9 @@
 import org.graalvm.compiler.code.CompilationResult.CodeAnnotation;
 import org.graalvm.compiler.code.CompilationResult.CodeComment;
 import org.graalvm.compiler.code.CompilationResult.JumpTable;
-import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.code.DataSection;
 import org.graalvm.compiler.code.SourceMapping;
+import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.graph.NodeSourcePosition;
 
 import jdk.vm.ci.code.CodeCacheProvider;
@@ -55,7 +57,6 @@
 import jdk.vm.ci.hotspot.HotSpotCompiledCode;
 import jdk.vm.ci.hotspot.HotSpotCompiledCode.Comment;
 import jdk.vm.ci.hotspot.HotSpotCompiledNmethod;
-import jdk.vm.ci.hotspot.HotSpotObjectConstant;
 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
 import jdk.vm.ci.meta.Assumptions.Assumption;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
@@ -210,16 +211,31 @@
         sites.addAll(target.getDataPatches());
         sites.addAll(target.getMarks());
 
-        /*
-         * Translate the source mapping into appropriate info points. In HotSpot only one position
-         * can really be represented and recording the end PC seems to give the best results and
-         * corresponds with what C1 and C2 do.
-         */
         if (codeCache.shouldDebugNonSafepoints()) {
+            /*
+             * Translate the source mapping into appropriate info points. In HotSpot only one
+             * position can really be represented and recording the end PC seems to give the best
+             * results and corresponds with what C1 and C2 do. HotSpot doesn't like to see these
+             * unless -XX:+DebugNonSafepoints is enabled, so don't emit them in that case.
+             */
+            List<Site> sourcePositionSites = new ArrayList<>();
             for (SourceMapping source : target.getSourceMappings()) {
-                sites.add(new Infopoint(source.getEndOffset(), new DebugInfo(source.getSourcePosition()), InfopointReason.BYTECODE_POSITION));
-                assert verifySourcePositionReceivers(source.getSourcePosition());
+                NodeSourcePosition sourcePosition = source.getSourcePosition();
+                assert sourcePosition.verify();
+                sourcePosition = sourcePosition.trim();
+                /*
+                 * Don't add BYTECODE_POSITION info points that would potentially create conflicts.
+                 * Under certain conditions the site's pc is not the pc that gets recorded by
+                 * HotSpot (see @code {CodeInstaller::site_Call}). So, avoid adding any source
+                 * positions that can potentially map to the same pc. To do that make sure that the
+                 * source mapping doesn't contain a pc of any important Site.
+                 */
+                if (sourcePosition != null && !anyMatch(sites, s -> source.contains(s.pcOffset))) {
+                    sourcePositionSites.add(new Infopoint(source.getEndOffset(), new DebugInfo(sourcePosition), InfopointReason.BYTECODE_POSITION));
+
+                }
             }
+            sites.addAll(sourcePositionSites);
         }
 
         SiteComparator c = new SiteComparator();
@@ -245,18 +261,4 @@
         }
         return sites.toArray(new Site[sites.size()]);
     }
-
-    /**
-     * Verifies that the captured receiver type agrees with the declared type of the method.
-     */
-    private static boolean verifySourcePositionReceivers(NodeSourcePosition start) {
-        NodeSourcePosition pos = start;
-        while (pos != null) {
-            if (pos.getReceiver() != null) {
-                assert ((HotSpotObjectConstant) pos.getReceiver()).asObject(pos.getMethod().getDeclaringClass()) != null;
-            }
-            pos = pos.getCaller();
-        }
-        return true;
-    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java	Fri Mar 16 22:59:32 2018 -0700
@@ -26,8 +26,8 @@
 import static org.graalvm.compiler.hotspot.HotSpotGraalOptionValues.GRAAL_OPTION_PROPERTY_PREFIX;
 
 import java.io.PrintStream;
+import java.util.Collections;
 import java.util.Map;
-import java.util.Collections;
 
 import org.graalvm.compiler.debug.MethodFilter;
 import org.graalvm.compiler.options.Option;
@@ -36,6 +36,7 @@
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.options.OptionsParser;
 import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
+import org.graalvm.compiler.serviceprovider.JDK9Method;
 
 import jdk.vm.ci.common.InitTimer;
 import jdk.vm.ci.hotspot.HotSpotJVMCICompilerFactory;
@@ -48,6 +49,22 @@
     private static MethodFilter[] graalCompileOnlyFilter;
     private static boolean compileGraalWithC1Only;
 
+    /**
+     * Module containing {@link HotSpotJVMCICompilerFactory}.
+     */
+    private Object jvmciModule;
+
+    /**
+     * Module containing {@link HotSpotGraalCompilerFactory}.
+     */
+    private Object graalModule;
+
+    /**
+     * Module containing the {@linkplain CompilerConfigurationFactory#selectFactory selected}
+     * configuration.
+     */
+    private Object compilerConfigurationModule;
+
     private final HotSpotGraalJVMCIServiceLocator locator;
 
     HotSpotGraalCompilerFactory(HotSpotGraalJVMCIServiceLocator locator) {
@@ -70,6 +87,10 @@
         assert options == null : "cannot select " + getClass() + " service more than once";
         options = HotSpotGraalOptionValues.HOTSPOT_OPTIONS;
         initializeGraalCompilePolicyFields(options);
+        if (!JDK9Method.Java8OrEarlier) {
+            jvmciModule = JDK9Method.getModule(HotSpotJVMCICompilerFactory.class);
+            graalModule = JDK9Method.getModule(HotSpotGraalCompilerFactory.class);
+        }
         /*
          * Exercise this code path early to encourage loading now. This doesn't solve problem of
          * deadlock during class loading but seems to eliminate it in practice.
@@ -102,7 +123,9 @@
         @Option(help = "In tiered mode compile Graal and JVMCI using optimized first tier code.", type = OptionType.Expert)
         public static final OptionKey<Boolean> CompileGraalWithC1Only = new OptionKey<>(true);
 
-        @Option(help = "A method filter selecting what should be compiled by Graal.  All other requests will be reduced to CompilationLevel.Simple.", type = OptionType.Expert)
+        @Option(help = "A filter applied to a method the VM has selected for compilation by Graal. " +
+                       "A method not matching the filter is redirected to a lower tier compiler. " +
+                       "The filter format is the same as for the MethodFilter option.", type = OptionType.Expert)
         public static final OptionKey<String> GraalCompileOnly = new OptionKey<>(null);
         // @formatter:on
 
@@ -110,7 +133,11 @@
 
     @Override
     public HotSpotGraalCompiler createCompiler(JVMCIRuntime runtime) {
-        HotSpotGraalCompiler compiler = createCompiler(runtime, options, CompilerConfigurationFactory.selectFactory(null, options));
+        CompilerConfigurationFactory factory = CompilerConfigurationFactory.selectFactory(null, options);
+        if (!JDK9Method.Java8OrEarlier) {
+            compilerConfigurationModule = JDK9Method.getModule(factory.getClass());
+        }
+        HotSpotGraalCompiler compiler = createCompiler(runtime, options, factory);
         // Only the HotSpotGraalRuntime associated with the compiler created via
         // jdk.vm.ci.runtime.JVMCIRuntime.getCompiler() is registered for receiving
         // VM events.
@@ -160,15 +187,54 @@
         assert HotSpotGraalCompilerFactory.class.getName().equals("org.graalvm.compiler.hotspot.HotSpotGraalCompilerFactory");
     }
 
+    static final ClassLoader JVMCI_LOADER = HotSpotGraalCompilerFactory.class.getClassLoader();
+
     /*
      * This method is static so it can be exercised during initialization.
      */
-    private static CompilationLevel adjustCompilationLevelInternal(Class<?> declaringClass, String name, String signature, CompilationLevel level) {
+    private CompilationLevel adjustCompilationLevelInternal(Class<?> declaringClass, String name, String signature, CompilationLevel level) {
         if (compileGraalWithC1Only) {
             if (level.ordinal() > CompilationLevel.Simple.ordinal()) {
-                String declaringClassName = declaringClass.getName();
-                if (declaringClassName.startsWith("jdk.vm.ci") || declaringClassName.startsWith("org.graalvm") || declaringClassName.startsWith("com.oracle.graal")) {
-                    return CompilationLevel.Simple;
+                if (JDK9Method.Java8OrEarlier) {
+                    if (JVMCI_LOADER != null) {
+                        // When running with +UseJVMCIClassLoader all classes in
+                        // the JVMCI loader should be compiled with C1.
+                        try {
+                            if (declaringClass.getClassLoader() == JVMCI_LOADER) {
+                                return CompilationLevel.Simple;
+                            }
+                        } catch (SecurityException e) {
+                            // This is definitely not a JVMCI or Graal class
+                        }
+                    } else {
+                        // JVMCI and Graal are on the bootclasspath so match based on the package.
+                        String declaringClassName = declaringClass.getName();
+                        if (declaringClassName.startsWith("jdk.vm.ci")) {
+                            return CompilationLevel.Simple;
+                        }
+                        if (declaringClassName.startsWith("org.graalvm.") &&
+                                        (declaringClassName.startsWith("org.graalvm.compiler.") ||
+                                                        declaringClassName.startsWith("org.graalvm.collections.") ||
+                                                        declaringClassName.startsWith("org.graalvm.compiler.word.") ||
+                                                        declaringClassName.startsWith("org.graalvm.graphio."))) {
+                            return CompilationLevel.Simple;
+                        }
+                        if (declaringClassName.startsWith("com.oracle.graal") &&
+                                        (declaringClassName.startsWith("com.oracle.graal.enterprise") ||
+                                                        declaringClassName.startsWith("com.oracle.graal.vector") ||
+                                                        declaringClassName.startsWith("com.oracle.graal.asm"))) {
+                            return CompilationLevel.Simple;
+                        }
+                    }
+                } else {
+                    try {
+                        Object module = JDK9Method.getModule(declaringClass);
+                        if (jvmciModule == module || graalModule == module || compilerConfigurationModule == module) {
+                            return CompilationLevel.Simple;
+                        }
+                    } catch (Throwable e) {
+                        throw new InternalError(e);
+                    }
                 }
             }
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/NodeCostDumpUtil.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/NodeCostDumpUtil.java	Fri Mar 16 22:59:32 2018 -0700
@@ -24,7 +24,6 @@
 
 import java.io.File;
 import java.io.IOException;
-import java.lang.reflect.Field;
 import java.net.URI;
 import java.net.URL;
 import java.net.URLClassLoader;
@@ -114,14 +113,9 @@
         }
         System.err.printf("Loaded %s node classes...\n", nodeClasses.size());
         List<NodeClass<?>> nc = new ArrayList<>();
-        for (Class<?> nodeClass : nodeClasses) {
-            Field f;
+        for (Class<?> c : nodeClasses) {
             try {
-                f = nodeClass.getField("TYPE");
-                f.setAccessible(true);
-                Object val = f.get(null);
-                NodeClass<?> nodeType = (NodeClass<?>) val;
-                nc.add(nodeType);
+                nc.add(NodeClass.get(c));
             } catch (Throwable t) {
                 // Silently ignore problems here
             }
--- /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/lir/VerifyMaxRegisterSizePhase.java	Fri Mar 16 22:59:32 2018 -0700
@@ -0,0 +1,77 @@
+/*
+ * 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.lir;
+
+import java.util.EnumSet;
+
+import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
+import org.graalvm.compiler.lir.LIR;
+import org.graalvm.compiler.lir.LIRInstruction;
+import org.graalvm.compiler.lir.gen.LIRGenerationResult;
+import org.graalvm.compiler.lir.phases.PostAllocationOptimizationPhase;
+
+import jdk.vm.ci.code.TargetDescription;
+import static jdk.vm.ci.code.ValueUtil.isRegister;
+import jdk.vm.ci.meta.Value;
+import org.graalvm.compiler.lir.LIRInstruction.OperandFlag;
+import org.graalvm.compiler.lir.LIRInstruction.OperandMode;
+
+/**
+ * Checks that no registers exceed the MaxVectorSize flag from the VM config.
+ */
+public final class VerifyMaxRegisterSizePhase extends PostAllocationOptimizationPhase {
+
+    private final int maxVectorSize;
+
+    public VerifyMaxRegisterSizePhase(int maxVectorSize) {
+        this.maxVectorSize = maxVectorSize;
+    }
+
+    @Override
+    protected void run(TargetDescription target, LIRGenerationResult lirGenRes, PostAllocationOptimizationContext context) {
+        LIR lir = lirGenRes.getLIR();
+        for (AbstractBlockBase<?> block : lir.getControlFlowGraph().getBlocks()) {
+            verifyBlock(lir, block);
+        }
+    }
+
+    protected void verifyBlock(LIR lir, AbstractBlockBase<?> block) {
+        for (LIRInstruction inst : lir.getLIRforBlock(block)) {
+            verifyInstruction(inst);
+        }
+    }
+
+    protected void verifyInstruction(LIRInstruction inst) {
+        inst.visitEachInput(this::verifyOperands);
+        inst.visitEachOutput(this::verifyOperands);
+        inst.visitEachAlive(this::verifyOperands);
+        inst.visitEachTemp(this::verifyOperands);
+    }
+
+    @SuppressWarnings("unused")
+    protected void verifyOperands(LIRInstruction instruction, Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
+        if (isRegister(value)) {
+            assert value.getPlatformKind().getSizeInBytes() <= maxVectorSize : "value " + value + " exceeds MaxVectorSize " + maxVectorSize;
+        }
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotClassInitializationPlugin.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotClassInitializationPlugin.java	Fri Mar 16 22:59:32 2018 -0700
@@ -25,6 +25,7 @@
 import org.graalvm.compiler.core.common.type.ObjectStamp;
 import org.graalvm.compiler.core.common.type.Stamp;
 import org.graalvm.compiler.core.common.type.StampFactory;
+import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode;
 import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode;
 import org.graalvm.compiler.nodes.ConstantNode;
@@ -37,6 +38,11 @@
 import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.meta.ConstantPool;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
 
 public final class HotSpotClassInitializationPlugin implements ClassInitializationPlugin {
     @Override
@@ -73,4 +79,47 @@
         result.setStateBefore(frameState);
         return result;
     }
+
+    private static final Class<? extends ConstantPool> hscp;
+    private static final MethodHandle loadReferencedTypeIIZMH;
+
+    static {
+        MethodHandle m = null;
+        Class<? extends ConstantPool> c = null;
+        try {
+            c = Class.forName("jdk.vm.ci.hotspot.HotSpotConstantPool").asSubclass(ConstantPool.class);
+            m = MethodHandles.lookup().findVirtual(c, "loadReferencedType", MethodType.methodType(void.class, int.class, int.class, boolean.class));
+        } catch (Exception e) {
+        }
+        loadReferencedTypeIIZMH = m;
+        hscp = c;
+    }
+
+    private static boolean isHotSpotConstantPool(ConstantPool cp) {
+        // jdk.vm.ci.hotspot.HotSpotConstantPool is final, so we can
+        // directly compare Classes.
+        return cp.getClass() == hscp;
+    }
+
+    @Override
+    public boolean supportsLazyInitialization(ConstantPool cp) {
+        if (loadReferencedTypeIIZMH != null && isHotSpotConstantPool(cp)) {
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void loadReferencedType(GraphBuilderContext builder, ConstantPool cp, int cpi, int opcode) {
+        if (loadReferencedTypeIIZMH != null && isHotSpotConstantPool(cp)) {
+            try {
+                loadReferencedTypeIIZMH.invoke(cp, cpi, opcode, false);
+            } catch (Throwable t) {
+                throw GraalError.shouldNotReachHere(t);
+            }
+        } else {
+            cp.loadReferencedType(cpi, opcode);
+        }
+    }
+
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java	Fri Mar 16 22:59:32 2018 -0700
@@ -234,7 +234,7 @@
                     b.addPush(JavaKind.Object, object);
                 } else {
                     FixedGuardNode fixedGuard = b.add(new FixedGuardNode(condition, DeoptimizationReason.ClassCastException, DeoptimizationAction.InvalidateReprofile, false));
-                    b.addPush(JavaKind.Object, new DynamicPiNode(object, fixedGuard, javaClass));
+                    b.addPush(JavaKind.Object, DynamicPiNode.create(b.getAssumptions(), b.getConstantReflection(), object, fixedGuard, javaClass));
                 }
                 return true;
             }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvocationPlugins.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvocationPlugins.java	Fri Mar 16 22:59:32 2018 -0700
@@ -24,6 +24,7 @@
 
 import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier;
 
+import java.lang.invoke.MethodHandle;
 import java.lang.reflect.Type;
 import java.util.Set;
 
@@ -129,7 +130,7 @@
                 ClassLoader cl = javaClass.getClassLoader();
                 return cl == null || cl == getClass().getClassLoader() || cl == extLoader;
             } else {
-                Object module = JDK9Method.getModule.invoke(javaClass);
+                Object module = JDK9Method.getModule(javaClass);
                 return trustedModules.contains(module);
             }
         }
@@ -148,34 +149,43 @@
         }
     }
 
+    /**
+     * Gets the set of modules whose methods can be intrinsified. This set is the module owning the
+     * class of {@code compilerConfiguration} and all its dependencies.
+     */
     private static EconomicSet<Object> initTrustedModules(CompilerConfiguration compilerConfiguration) throws GraalError {
         try {
             EconomicSet<Object> res = EconomicSet.create();
-            Object compilerConfigurationModule = JDK9Method.getModule.invoke(compilerConfiguration.getClass());
+            Object compilerConfigurationModule = JDK9Method.getModule(compilerConfiguration.getClass());
             res.add(compilerConfigurationModule);
             Class<?> moduleClass = compilerConfigurationModule.getClass();
-            Object layer = new JDK9Method(moduleClass, "getLayer").invoke(compilerConfigurationModule);
+            Object layer = JDK9Method.lookupMethodHandle(moduleClass, "getLayer").invoke(compilerConfigurationModule);
             Class<? extends Object> layerClass = layer.getClass();
-            JDK9Method getName = new JDK9Method(moduleClass, "getName");
-            Set<Object> modules = new JDK9Method(layerClass, "modules").invoke(layer);
-            Object descriptor = new JDK9Method(moduleClass, "getDescriptor").invoke(compilerConfigurationModule);
+            MethodHandle getName = JDK9Method.lookupMethodHandle(moduleClass, "getName");
+            Set<Object> modules = (Set<Object>) JDK9Method.lookupMethodHandle(layerClass, "modules").invoke(layer);
+            Object descriptor = JDK9Method.lookupMethodHandle(moduleClass, "getDescriptor").invoke(compilerConfigurationModule);
             Class<?> moduleDescriptorClass = descriptor.getClass();
-            Set<Object> requires = new JDK9Method(moduleDescriptorClass, "requires").invoke(descriptor);
-            JDK9Method requireNameGetter = null;
+            Set<Object> requires = (Set<Object>) JDK9Method.lookupMethodHandle(moduleDescriptorClass, "requires").invoke(descriptor);
+            boolean isAutomatic = (Boolean) JDK9Method.lookupMethodHandle(moduleDescriptorClass, "isAutomatic").invoke(descriptor);
+            if (isAutomatic) {
+                throw new IllegalArgumentException(String.format("The module '%s' defining the Graal compiler configuration class '%s' must not be an automatic module",
+                                getName.invoke(compilerConfigurationModule), compilerConfiguration.getClass().getName()));
+            }
+            MethodHandle requireNameGetter = null;
             for (Object require : requires) {
                 if (requireNameGetter == null) {
-                    requireNameGetter = new JDK9Method(require.getClass(), "name");
+                    requireNameGetter = JDK9Method.lookupMethodHandle(require.getClass(), "name");
                 }
-                String name = requireNameGetter.invoke(require);
+                String name = (String) requireNameGetter.invoke(require);
                 for (Object module : modules) {
-                    String moduleName = getName.invoke(module);
+                    String moduleName = (String) getName.invoke(module);
                     if (moduleName.equals(name)) {
                         res.add(module);
                     }
                 }
             }
             return res;
-        } catch (Exception e) {
+        } catch (Throwable e) {
             throw new GraalError(e);
         }
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java	Fri Mar 16 22:59:32 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -28,11 +28,13 @@
 import static org.graalvm.compiler.core.phases.HighTier.Options.Inline;
 
 import java.util.ListIterator;
+import org.graalvm.compiler.debug.Assertions;
 
 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
 import org.graalvm.compiler.hotspot.HotSpotBackend;
 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
 import org.graalvm.compiler.hotspot.HotSpotInstructionProfiling;
+import org.graalvm.compiler.hotspot.lir.VerifyMaxRegisterSizePhase;
 import org.graalvm.compiler.hotspot.phases.AheadOfTimeVerificationPhase;
 import org.graalvm.compiler.hotspot.phases.LoadJavaMirrorWithKlassPhase;
 import org.graalvm.compiler.hotspot.phases.WriteBarrierAdditionPhase;
@@ -139,6 +141,10 @@
                 StructuredGraph targetGraph = new StructuredGraph.Builder(graph.getOptions(), graph.getDebug(), AllowAssumptions.YES).method(graph.method()).build();
                 SimplifyingGraphDecoder graphDecoder = new SimplifyingGraphDecoder(runtime.getTarget().arch, targetGraph, context.getMetaAccess(), context.getConstantReflection(),
                                 context.getConstantFieldProvider(), context.getStampProvider(), !ImmutableCode.getValue(graph.getOptions()));
+
+                if (graph.trackNodeSourcePosition()) {
+                    targetGraph.setTrackNodeSourcePosition();
+                }
                 graphDecoder.decode(encodedGraph);
             }
 
@@ -171,6 +177,9 @@
         if (profileInstructions != null) {
             suites.getPostAllocationOptimizationStage().appendPhase(new HotSpotInstructionProfiling(profileInstructions));
         }
+        if (Assertions.detailedAssertionsEnabled(options)) {
+            suites.getPostAllocationOptimizationStage().appendPhase(new VerifyMaxRegisterSizePhase(config.maxVectorSize));
+        }
         return suites;
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/AOTInliningPolicy.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/AOTInliningPolicy.java	Fri Mar 16 22:59:32 2018 -0700
@@ -76,17 +76,17 @@
 
         OptionValues options = info.graph().getOptions();
         if (InlineEverything.getValue(options)) {
-            InliningUtil.logInlinedMethod(info, inliningDepth, fullyProcessed, "inline everything");
+            InliningUtil.traceInlinedMethod(info, inliningDepth, fullyProcessed, "inline everything");
             return true;
         }
 
         if (isIntrinsic(replacements, info)) {
-            InliningUtil.logInlinedMethod(info, inliningDepth, fullyProcessed, "intrinsic");
+            InliningUtil.traceInlinedMethod(info, inliningDepth, fullyProcessed, "intrinsic");
             return true;
         }
 
         if (info.shouldInline()) {
-            InliningUtil.logInlinedMethod(info, inliningDepth, fullyProcessed, "forced inlining");
+            InliningUtil.traceInlinedMethod(info, inliningDepth, fullyProcessed, "forced inlining");
             return true;
         }
 
@@ -94,18 +94,18 @@
         int nodes = info.determineNodeCount();
 
         if (nodes < TrivialInliningSize.getValue(options) * inliningBonus) {
-            InliningUtil.logInlinedMethod(info, inliningDepth, fullyProcessed, "trivial (relevance=%f, probability=%f, bonus=%f, nodes=%d)", relevance, probability, inliningBonus, nodes);
+            InliningUtil.traceInlinedMethod(info, inliningDepth, fullyProcessed, "trivial (relevance=%f, probability=%f, bonus=%f, nodes=%d)", relevance, probability, inliningBonus, nodes);
             return true;
         }
 
         double maximumNodes = computeMaximumSize(relevance, (int) (maxInliningSize(inliningDepth, options) * inliningBonus));
         if (nodes <= maximumNodes) {
-            InliningUtil.logInlinedMethod(info, inliningDepth, fullyProcessed, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d <= %f)", relevance, probability, inliningBonus,
+            InliningUtil.traceInlinedMethod(info, inliningDepth, fullyProcessed, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d <= %f)", relevance, probability, inliningBonus,
                             nodes, maximumNodes);
             return true;
         }
 
-        InliningUtil.logNotInlinedMethod(info, inliningDepth, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d > %f)", relevance, probability, inliningBonus, nodes, maximumNodes);
+        InliningUtil.traceNotInlinedMethod(info, inliningDepth, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d > %f)", relevance, probability, inliningBonus, nodes, maximumNodes);
         return false;
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/AssertionSnippets.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/AssertionSnippets.java	Fri Mar 16 22:59:32 2018 -0700
@@ -86,7 +86,7 @@
             args.add("condition", assertionNode.condition());
             args.addConst("message", "failed runtime assertion in snippet/stub: " + assertionNode.message() + " (" + graph.method() + ")");
 
-            template(assertionNode.getDebug(), args).instantiate(providers.getMetaAccess(), assertionNode, DEFAULT_REPLACER, args);
+            template(assertionNode, args).instantiate(providers.getMetaAccess(), assertionNode, DEFAULT_REPLACER, args);
         }
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HashCodeSnippets.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HashCodeSnippets.java	Fri Mar 16 22:59:32 2018 -0700
@@ -87,7 +87,7 @@
             StructuredGraph graph = node.graph();
             Arguments args = new Arguments(identityHashCodeSnippet, graph.getGuardsStage(), tool.getLoweringStage());
             args.add("thisObj", node.object);
-            SnippetTemplate template = template(node.getDebug(), args);
+            SnippetTemplate template = template(node, args);
             template.instantiate(providers.getMetaAccess(), node, SnippetTemplate.DEFAULT_REPLACER, args);
         }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/LoadExceptionObjectSnippets.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/LoadExceptionObjectSnippets.java	Fri Mar 16 22:59:32 2018 -0700
@@ -101,7 +101,7 @@
             } else {
                 Arguments args = new Arguments(loadException, loadExceptionObject.graph().getGuardsStage(), tool.getLoweringStage());
                 args.addConst("threadRegister", registers.getThreadRegister());
-                template(loadExceptionObject.getDebug(), args).instantiate(providers.getMetaAccess(), loadExceptionObject, DEFAULT_REPLACER, args);
+                template(loadExceptionObject, args).instantiate(providers.getMetaAccess(), loadExceptionObject, DEFAULT_REPLACER, args);
             }
         }
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java	Fri Mar 16 22:59:32 2018 -0700
@@ -759,7 +759,7 @@
                 args.addConst("counters", counters);
             }
 
-            template(graph.getDebug(), args).instantiate(providers.getMetaAccess(), monitorenterNode, DEFAULT_REPLACER, args);
+            template(monitorenterNode, args).instantiate(providers.getMetaAccess(), monitorenterNode, DEFAULT_REPLACER, args);
         }
 
         public void lower(MonitorExitNode monitorexitNode, HotSpotRegistersProvider registers, LoweringTool tool) {
@@ -778,7 +778,7 @@
             args.addConst("options", graph.getOptions());
             args.addConst("counters", counters);
 
-            template(graph.getDebug(), args).instantiate(providers.getMetaAccess(), monitorexitNode, DEFAULT_REPLACER, args);
+            template(monitorexitNode, args).instantiate(providers.getMetaAccess(), monitorexitNode, DEFAULT_REPLACER, args);
         }
 
         public static boolean isTracingEnabledForType(ValueNode object) {
@@ -828,7 +828,7 @@
                     invoke.setStateAfter(graph.start().stateAfter());
                     graph.addAfterFixed(graph.start(), invoke);
 
-                    StructuredGraph inlineeGraph = providers.getReplacements().getSnippet(initCounter.getMethod(), null);
+                    StructuredGraph inlineeGraph = providers.getReplacements().getSnippet(initCounter.getMethod(), null, invoke.graph().trackNodeSourcePosition(), invoke.getNodeSourcePosition());
                     InliningUtil.inline(invoke, inlineeGraph, false, null);
 
                     List<ReturnNode> rets = graph.getNodes(ReturnNode.TYPE).snapshot();
@@ -846,7 +846,7 @@
 
                         Arguments args = new Arguments(checkCounter, graph.getGuardsStage(), tool.getLoweringStage());
                         args.addConst("errMsg", msg);
-                        inlineeGraph = template(graph.getDebug(), args).copySpecializedGraph(graph.getDebug());
+                        inlineeGraph = template(invoke, args).copySpecializedGraph(graph.getDebug());
                         InliningUtil.inline(invoke, inlineeGraph, false, null);
                     }
                 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java	Fri Mar 16 22:59:32 2018 -0700
@@ -626,7 +626,7 @@
             args.addConst("options", localOptions);
             args.addConst("counters", counters);
 
-            SnippetTemplate template = template(graph.getDebug(), args);
+            SnippetTemplate template = template(newInstanceNode, args);
             graph.getDebug().log("Lowering allocateInstance in %s: node=%s, template=%s, arguments=%s", graph, newInstanceNode, template, args);
             template.instantiate(providers.getMetaAccess(), newInstanceNode, DEFAULT_REPLACER, args);
         }
@@ -669,7 +669,7 @@
             args.addConst("typeContext", ProfileAllocations.getValue(localOptions) ? arrayType.toJavaName(false) : "");
             args.addConst("options", localOptions);
             args.addConst("counters", counters);
-            SnippetTemplate template = template(graph.getDebug(), args);
+            SnippetTemplate template = template(newArrayNode, args);
             graph.getDebug().log("Lowering allocateArray in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, args);
             template.instantiate(providers.getMetaAccess(), newArrayNode, DEFAULT_REPLACER, args);
         }
@@ -686,7 +686,7 @@
             args.addConst("options", localOptions);
             args.addConst("counters", counters);
 
-            SnippetTemplate template = template(newInstanceNode.getDebug(), args);
+            SnippetTemplate template = template(newInstanceNode, args);
             template.instantiate(providers.getMetaAccess(), newInstanceNode, DEFAULT_REPLACER, args);
         }
 
@@ -715,7 +715,7 @@
             args.add("prototypeMarkWord", lookupArrayClass(tool, JavaKind.Object).prototypeMarkWord());
             args.addConst("options", localOptions);
             args.addConst("counters", counters);
-            SnippetTemplate template = template(graph.getDebug(), args);
+            SnippetTemplate template = template(newArrayNode, args);
             template.instantiate(providers.getMetaAccess(), newArrayNode, DEFAULT_REPLACER, args);
         }
 
@@ -739,7 +739,7 @@
             args.add("hub", hub);
             args.addConst("rank", rank);
             args.addVarargs("dimensions", int.class, StampFactory.forKind(JavaKind.Int), dims);
-            template(newmultiarrayNode.getDebug(), args).instantiate(providers.getMetaAccess(), newmultiarrayNode, DEFAULT_REPLACER, args);
+            template(newmultiarrayNode, args).instantiate(providers.getMetaAccess(), newmultiarrayNode, DEFAULT_REPLACER, args);
         }
 
         private static int instanceSize(HotSpotResolvedObjectType type) {
@@ -753,7 +753,7 @@
                 Arguments args = new Arguments(verifyHeap, verifyHeapNode.graph().getGuardsStage(), tool.getLoweringStage());
                 args.addConst("threadRegister", registers.getThreadRegister());
 
-                SnippetTemplate template = template(verifyHeapNode.getDebug(), args);
+                SnippetTemplate template = template(verifyHeapNode, args);
                 template.instantiate(providers.getMetaAccess(), verifyHeapNode, DEFAULT_REPLACER, args);
             } else {
                 GraphUtil.removeFixedWithUnusedInputs(verifyHeapNode);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ObjectCloneNode.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ObjectCloneNode.java	Fri Mar 16 22:59:32 2018 -0700
@@ -86,7 +86,7 @@
                     StructuredGraph snippetGraph = null;
                     DebugContext debug = getDebug();
                     try (DebugContext.Scope s = debug.scope("ArrayCloneSnippet", snippetMethod)) {
-                        snippetGraph = replacements.getSnippet(snippetMethod, null);
+                        snippetGraph = replacements.getSnippet(snippetMethod, null, graph().trackNodeSourcePosition(), this.getNodeSourcePosition());
                     } catch (Throwable e) {
                         throw debug.handle(e);
                     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/StringToBytesSnippets.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/StringToBytesSnippets.java	Fri Mar 16 22:59:32 2018 -0700
@@ -83,7 +83,7 @@
         public void lower(StringToBytesNode stringToBytesNode, LoweringTool tool) {
             Arguments args = new Arguments(create, stringToBytesNode.graph().getGuardsStage(), tool.getLoweringStage());
             args.addConst("compilationTimeString", stringToBytesNode.getValue());
-            SnippetTemplate template = template(stringToBytesNode.getDebug(), args);
+            SnippetTemplate template = template(stringToBytesNode, args);
             template.instantiate(providers.getMetaAccess(), stringToBytesNode, DEFAULT_REPLACER, args);
         }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/UnsafeLoadSnippets.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/UnsafeLoadSnippets.java	Fri Mar 16 22:59:32 2018 -0700
@@ -65,7 +65,7 @@
             Arguments args = new Arguments(unsafeLoad, load.graph().getGuardsStage(), tool.getLoweringStage());
             args.add("object", load.object());
             args.add("offset", load.offset());
-            template(load.getDebug(), args).instantiate(providers.getMetaAccess(), load, DEFAULT_REPLACER, args);
+            template(load, args).instantiate(providers.getMetaAccess(), load, DEFAULT_REPLACER, args);
         }
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java	Fri Mar 16 22:59:32 2018 -0700
@@ -434,7 +434,7 @@
                 args.add("object", address.getBase());
             }
             args.addConst("counters", counters);
-            template(writeBarrier.getDebug(), args).instantiate(providers.getMetaAccess(), writeBarrier, DEFAULT_REPLACER, args);
+            template(writeBarrier, args).instantiate(providers.getMetaAccess(), writeBarrier, DEFAULT_REPLACER, args);
         }
 
         public void lower(SerialArrayRangeWriteBarrier arrayRangeWriteBarrier, LoweringTool tool) {
@@ -442,7 +442,7 @@
             args.add("address", arrayRangeWriteBarrier.getAddress());
             args.add("length", arrayRangeWriteBarrier.getLength());
             args.addConst("elementStride", arrayRangeWriteBarrier.getElementStride());
-            template(arrayRangeWriteBarrier.getDebug(), args).instantiate(providers.getMetaAccess(), arrayRangeWriteBarrier, DEFAULT_REPLACER, args);
+            template(arrayRangeWriteBarrier, args).instantiate(providers.getMetaAccess(), arrayRangeWriteBarrier, DEFAULT_REPLACER, args);
         }
 
         public void lower(G1PreWriteBarrier writeBarrierPre, HotSpotRegistersProvider registers, LoweringTool tool) {
@@ -467,7 +467,7 @@
             args.addConst("threadRegister", registers.getThreadRegister());
             args.addConst("trace", traceBarrier(writeBarrierPre.graph()));
             args.addConst("counters", counters);
-            template(writeBarrierPre.getDebug(), args).instantiate(providers.getMetaAccess(), writeBarrierPre, DEFAULT_REPLACER, args);
+            template(writeBarrierPre, args).instantiate(providers.getMetaAccess(), writeBarrierPre, DEFAULT_REPLACER, args);
         }
 
         public void lower(G1ReferentFieldReadBarrier readBarrier, HotSpotRegistersProvider registers, LoweringTool tool) {
@@ -492,7 +492,7 @@
             args.addConst("threadRegister", registers.getThreadRegister());
             args.addConst("trace", traceBarrier(readBarrier.graph()));
             args.addConst("counters", counters);
-            template(readBarrier.getDebug(), args).instantiate(providers.getMetaAccess(), readBarrier, DEFAULT_REPLACER, args);
+            template(readBarrier, args).instantiate(providers.getMetaAccess(), readBarrier, DEFAULT_REPLACER, args);
         }
 
         public void lower(G1PostWriteBarrier writeBarrierPost, HotSpotRegistersProvider registers, LoweringTool tool) {
@@ -522,7 +522,7 @@
             args.addConst("threadRegister", registers.getThreadRegister());
             args.addConst("trace", traceBarrier(writeBarrierPost.graph()));
             args.addConst("counters", counters);
-            template(graph.getDebug(), args).instantiate(providers.getMetaAccess(), writeBarrierPost, DEFAULT_REPLACER, args);
+            template(writeBarrierPost, args).instantiate(providers.getMetaAccess(), writeBarrierPost, DEFAULT_REPLACER, args);
         }
 
         public void lower(G1ArrayRangePreWriteBarrier arrayRangeWriteBarrier, HotSpotRegistersProvider registers, LoweringTool tool) {
@@ -531,7 +531,7 @@
             args.add("length", arrayRangeWriteBarrier.getLength());
             args.addConst("elementStride", arrayRangeWriteBarrier.getElementStride());
             args.addConst("threadRegister", registers.getThreadRegister());
-            template(arrayRangeWriteBarrier.getDebug(), args).instantiate(providers.getMetaAccess(), arrayRangeWriteBarrier, DEFAULT_REPLACER, args);
+            template(arrayRangeWriteBarrier, args).instantiate(providers.getMetaAccess(), arrayRangeWriteBarrier, DEFAULT_REPLACER, args);
         }
 
         public void lower(G1ArrayRangePostWriteBarrier arrayRangeWriteBarrier, HotSpotRegistersProvider registers, LoweringTool tool) {
@@ -540,7 +540,7 @@
             args.add("length", arrayRangeWriteBarrier.getLength());
             args.addConst("elementStride", arrayRangeWriteBarrier.getElementStride());
             args.addConst("threadRegister", registers.getThreadRegister());
-            template(arrayRangeWriteBarrier.getDebug(), args).instantiate(providers.getMetaAccess(), arrayRangeWriteBarrier, DEFAULT_REPLACER, args);
+            template(arrayRangeWriteBarrier, args).instantiate(providers.getMetaAccess(), arrayRangeWriteBarrier, DEFAULT_REPLACER, args);
         }
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/aot/ResolveConstantSnippets.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/aot/ResolveConstantSnippets.java	Fri Mar 16 22:59:32 2018 -0700
@@ -36,10 +36,10 @@
 import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassStubCall;
 import org.graalvm.compiler.hotspot.nodes.aot.LoadConstantIndirectlyNode;
 import org.graalvm.compiler.hotspot.nodes.aot.LoadMethodCountersIndirectlyNode;
+import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode;
+import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantStubCall;
+import org.graalvm.compiler.hotspot.nodes.aot.ResolveDynamicConstantNode;
 import org.graalvm.compiler.hotspot.nodes.aot.ResolveDynamicStubCall;
-import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode;
-import org.graalvm.compiler.hotspot.nodes.aot.ResolveDynamicConstantNode;
-import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantStubCall;
 import org.graalvm.compiler.hotspot.nodes.aot.ResolveMethodAndLoadCountersNode;
 import org.graalvm.compiler.hotspot.nodes.aot.ResolveMethodAndLoadCountersStubCall;
 import org.graalvm.compiler.hotspot.nodes.type.MethodPointerStamp;
@@ -141,7 +141,7 @@
             Arguments args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage());
             args.add("constant", value);
 
-            SnippetTemplate template = template(graph.getDebug(), args);
+            SnippetTemplate template = template(resolveConstantNode, args);
             template.instantiate(providers.getMetaAccess(), resolveConstantNode, DEFAULT_REPLACER, args);
 
             assert resolveConstantNode.hasNoUsages();
@@ -180,7 +180,7 @@
             Arguments args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage());
             args.add("constant", value);
 
-            SnippetTemplate template = template(graph.getDebug(), args);
+            SnippetTemplate template = template(resolveConstantNode, args);
             template.instantiate(providers.getMetaAccess(), resolveConstantNode, DEFAULT_REPLACER, args);
 
             assert resolveConstantNode.hasNoUsages();
@@ -200,7 +200,7 @@
                 Arguments args = new Arguments(initializeKlass, graph.getGuardsStage(), tool.getLoweringStage());
                 args.add("constant", value);
 
-                SnippetTemplate template = template(graph.getDebug(), args);
+                SnippetTemplate template = template(initializeKlassNode, args);
                 template.instantiate(providers.getMetaAccess(), initializeKlassNode, DEFAULT_REPLACER, args);
                 assert initializeKlassNode.hasNoUsages();
                 if (!initializeKlassNode.isDeleted()) {
@@ -218,7 +218,7 @@
             Arguments args = new Arguments(resolveMethodAndLoadCounters, graph.getGuardsStage(), tool.getLoweringStage());
             args.add("method", method);
             args.add("klassHint", resolveMethodAndLoadCountersNode.getHub());
-            SnippetTemplate template = template(graph.getDebug(), args);
+            SnippetTemplate template = template(resolveMethodAndLoadCountersNode, args);
             template.instantiate(providers.getMetaAccess(), resolveMethodAndLoadCountersNode, DEFAULT_REPLACER, args);
 
             assert resolveMethodAndLoadCountersNode.hasNoUsages();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java	Fri Mar 16 22:59:32 2018 -0700
@@ -524,7 +524,7 @@
          */
         private void instantiate(Arguments args, BasicArrayCopyNode arraycopy) {
             StructuredGraph graph = arraycopy.graph();
-            SnippetTemplate template = template(graph.getDebug(), args);
+            SnippetTemplate template = template(arraycopy, args);
             UnmodifiableEconomicMap<Node, Node> replacements = template.instantiate(providers.getMetaAccess(), arraycopy, SnippetTemplate.DEFAULT_REPLACER, args, false);
             for (Node originalNode : replacements.getKeys()) {
                 if (originalNode instanceof Invoke) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProbabilisticProfileSnippets.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProbabilisticProfileSnippets.java	Fri Mar 16 22:59:32 2018 -0700
@@ -150,7 +150,7 @@
                 args.add("bci", bci);
                 args.add("targetBci", targetBci);
 
-                SnippetTemplate template = template(graph.getDebug(), args);
+                SnippetTemplate template = template(profileNode, args);
                 template.instantiate(providers.getMetaAccess(), profileNode, DEFAULT_REPLACER, args);
             } else if (profileNode instanceof ProfileInvokeNode) {
                 ProfileInvokeNode profileInvokeNode = (ProfileInvokeNode) profileNode;
@@ -163,7 +163,7 @@
                 args.add("stepLog", stepLog);
                 args.addConst("freqLog", profileInvokeNode.getNotificationFreqLog());
                 args.addConst("probLog", profileInvokeNode.getProbabilityLog());
-                SnippetTemplate template = template(graph.getDebug(), args);
+                SnippetTemplate template = template(profileNode, args);
                 template.instantiate(providers.getMetaAccess(), profileNode, DEFAULT_REPLACER, args);
             } else {
                 throw new GraalError("Unsupported profile node type: " + profileNode);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProfileSnippets.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProfileSnippets.java	Fri Mar 16 22:59:32 2018 -0700
@@ -132,7 +132,7 @@
                 args.add("bci", bci);
                 args.add("targetBci", targetBci);
 
-                SnippetTemplate template = template(graph.getDebug(), args);
+                SnippetTemplate template = template(profileNode, args);
                 template.instantiate(providers.getMetaAccess(), profileNode, DEFAULT_REPLACER, args);
             } else if (profileNode instanceof ProfileInvokeNode) {
                 ProfileInvokeNode profileInvokeNode = (ProfileInvokeNode) profileNode;
@@ -142,7 +142,7 @@
                 args.add("step", step);
                 args.add("stepLog", stepLog);
                 args.addConst("freqLog", profileInvokeNode.getNotificationFreqLog());
-                SnippetTemplate template = template(graph.getDebug(), args);
+                SnippetTemplate template = template(profileNode, args);
                 template.instantiate(providers.getMetaAccess(), profileNode, DEFAULT_REPLACER, args);
             } else {
                 throw new GraalError("Unsupported profile node type: " + profileNode);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallStub.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallStub.java	Fri Mar 16 22:59:32 2018 -0700
@@ -34,8 +34,11 @@
 import org.graalvm.compiler.core.common.type.Stamp;
 import org.graalvm.compiler.core.common.type.StampFactory;
 import org.graalvm.compiler.core.common.type.StampPair;
+import org.graalvm.compiler.debug.DebugCloseable;
 import org.graalvm.compiler.debug.DebugContext;
+import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.debug.JavaMethodContext;
+import org.graalvm.compiler.graph.NodeSourcePosition;
 import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
 import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition;
 import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkageImpl;
@@ -224,33 +227,37 @@
      * %r15 on AMD64) and is only prepended if {@link #prependThread} is true.
      */
     @Override
+    @SuppressWarnings("try")
     protected StructuredGraph getGraph(DebugContext debug, CompilationIdentifier compilationId) {
         WordTypes wordTypes = providers.getWordTypes();
         Class<?>[] args = linkage.getDescriptor().getArgumentTypes();
         boolean isObjectResult = !LIRKind.isValue(linkage.getOutgoingCallingConvention().getReturn());
         StructuredGraph graph = new StructuredGraph.Builder(options, debug).name(toString()).compilationId(compilationId).build();
         graph.disableUnsafeAccessTracking();
+        graph.setTrackNodeSourcePosition();
+        try {
+            ResolvedJavaMethod thisMethod = providers.getMetaAccess().lookupJavaMethod(ForeignCallStub.class.getDeclaredMethod("getGraph", DebugContext.class, CompilationIdentifier.class));
+            try (DebugCloseable context = graph.withNodeSourcePosition(NodeSourcePosition.substitution(thisMethod))) {
+                GraphKit kit = new GraphKit(graph, providers, wordTypes, providers.getGraphBuilderPlugins());
+                ParameterNode[] params = createParameters(kit, args);
+                ReadRegisterNode thread = kit.append(new ReadRegisterNode(providers.getRegisters().getThreadRegister(), wordTypes.getWordKind(), true, false));
+                ValueNode result = createTargetCall(kit, params, thread);
+                kit.createInvoke(StubUtil.class, "handlePendingException", thread, ConstantNode.forBoolean(isObjectResult, graph));
+                if (isObjectResult) {
+                    InvokeNode object = kit.createInvoke(HotSpotReplacementsUtil.class, "getAndClearObjectResult", thread);
+                    result = kit.createInvoke(StubUtil.class, "verifyObject", object);
+                }
+                kit.append(new ReturnNode(linkage.getDescriptor().getResultType() == void.class ? null : result));
+                debug.dump(DebugContext.VERBOSE_LEVEL, graph, "Initial stub graph");
 
-        GraphKit kit = new GraphKit(graph, providers, wordTypes, providers.getGraphBuilderPlugins());
-        ParameterNode[] params = createParameters(kit, args);
+                kit.inlineInvokes();
+                new RemoveValueProxyPhase().apply(graph);
 
-        ReadRegisterNode thread = kit.append(new ReadRegisterNode(providers.getRegisters().getThreadRegister(), wordTypes.getWordKind(), true, false));
-        ValueNode result = createTargetCall(kit, params, thread);
-        kit.createInvoke(StubUtil.class, "handlePendingException", thread, ConstantNode.forBoolean(isObjectResult, graph));
-        if (isObjectResult) {
-            InvokeNode object = kit.createInvoke(HotSpotReplacementsUtil.class, "getAndClearObjectResult", thread);
-            result = kit.createInvoke(StubUtil.class, "verifyObject", object);
+                debug.dump(DebugContext.VERBOSE_LEVEL, graph, "Stub graph before compilation");
+            }
+        } catch (Exception e) {
+            throw GraalError.shouldNotReachHere(e);
         }
-        kit.append(new ReturnNode(linkage.getDescriptor().getResultType() == void.class ? null : result));
-
-        debug.dump(DebugContext.VERBOSE_LEVEL, graph, "Initial stub graph");
-
-        kit.inlineInvokes();
-
-        new RemoveValueProxyPhase().apply(graph);
-
-        debug.dump(DebugContext.VERBOSE_LEVEL, graph, "Stub graph before compilation");
-
         return graph;
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java	Fri Mar 16 22:59:32 2018 -0700
@@ -279,6 +279,7 @@
 import org.graalvm.compiler.bytecode.Bytes;
 import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode;
 import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecodeProvider;
+import org.graalvm.compiler.core.common.GraalOptions;
 import org.graalvm.compiler.core.common.PermanentBailoutException;
 import org.graalvm.compiler.core.common.calc.CanonicalCondition;
 import org.graalvm.compiler.core.common.calc.Condition;
@@ -678,6 +679,8 @@
 
     private boolean finalBarrierRequired;
     private ValueNode originalReceiver;
+    private final boolean eagerInitializing;
+    private final boolean uninitializedIsError;
 
     protected BytecodeParser(GraphBuilderPhase.Instance graphBuilderInstance, StructuredGraph graph, BytecodeParser parent, ResolvedJavaMethod method,
                     int entryBCI, IntrinsicContext intrinsicContext) {
@@ -701,6 +704,14 @@
         this.entryBCI = entryBCI;
         this.parent = parent;
 
+        ClassInitializationPlugin classInitializationPlugin = graphBuilderConfig.getPlugins().getClassInitializationPlugin();
+        if (classInitializationPlugin != null && graphBuilderConfig.eagerResolving()) {
+            uninitializedIsError = eagerInitializing = !classInitializationPlugin.supportsLazyInitialization(constantPool);
+        } else {
+            eagerInitializing = graphBuilderConfig.eagerResolving();
+            uninitializedIsError = graphBuilderConfig.unresolvedIsError();
+        }
+
         assert code.getCode() != null : "method must contain bytecodes: " + method;
 
         if (TraceBytecodeParserLevel.getValue(options) != 0) {
@@ -713,6 +724,11 @@
             lnt = code.getLineNumberTable();
             previousLineNumber = -1;
         }
+
+        assert !GraalOptions.TrackNodeSourcePosition.getValue(options) || graph.trackNodeSourcePosition();
+        if (graphBuilderConfig.trackNodeSourcePosition() || (parent != null && parent.graph.trackNodeSourcePosition())) {
+            graph.setTrackNodeSourcePosition();
+        }
     }
 
     protected GraphBuilderPhase.Instance getGraphBuilderInstance() {
@@ -807,26 +823,28 @@
                 }
             }
 
-            if (method.isSynchronized()) {
-                finishPrepare(lastInstr, BytecodeFrame.BEFORE_BCI);
-
-                // add a monitor enter to the start block
-                methodSynchronizedObject = synchronizedObject(frameState, method);
-                frameState.clearNonLiveLocals(startBlock, liveness, true);
-                assert bci() == 0;
-                genMonitorEnter(methodSynchronizedObject, bci());
+            try (DebugCloseable context = openNodeContext()) {
+                if (method.isSynchronized()) {
+                    finishPrepare(lastInstr, BytecodeFrame.BEFORE_BCI);
+
+                    // add a monitor enter to the start block
+                    methodSynchronizedObject = synchronizedObject(frameState, method);
+                    frameState.clearNonLiveLocals(startBlock, liveness, true);
+                    assert bci() == 0;
+                    genMonitorEnter(methodSynchronizedObject, bci());
+                }
+
+                ProfilingPlugin profilingPlugin = this.graphBuilderConfig.getPlugins().getProfilingPlugin();
+                if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
+                    FrameState stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null);
+                    profilingPlugin.profileInvoke(this, method, stateBefore);
+                }
+
+                finishPrepare(lastInstr, 0);
+
+                genInfoPointNode(InfopointReason.METHOD_START, null);
             }
 
-            ProfilingPlugin profilingPlugin = this.graphBuilderConfig.getPlugins().getProfilingPlugin();
-            if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
-                FrameState stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null);
-                profilingPlugin.profileInvoke(this, method, stateBefore);
-            }
-
-            finishPrepare(lastInstr, 0);
-
-            genInfoPointNode(InfopointReason.METHOD_START, null);
-
             currentBlock = blockMap.getStartBlock();
             setEntryState(startBlock, frameState);
             if (startBlock.isLoopHeader) {
@@ -1338,6 +1356,8 @@
 
     protected void genInvokeStatic(int cpi, int opcode) {
         JavaMethod target = lookupMethod(cpi, opcode);
+        assert !uninitializedIsError ||
+                        (target instanceof ResolvedJavaMethod && ((ResolvedJavaMethod) target).getDeclaringClass().isInitialized()) : target;
         genInvokeStatic(target);
     }
 
@@ -2017,6 +2037,7 @@
         }
     }
 
+    @SuppressWarnings("try")
     protected boolean tryInvocationPlugin(InvokeKind invokeKind, ValueNode[] args, ResolvedJavaMethod targetMethod, JavaKind resultType, JavaType returnType) {
         InvocationPlugin plugin = graphBuilderConfig.getPlugins().getInvocationPlugins().lookupInvocation(targetMethod);
         if (plugin != null) {
@@ -2041,11 +2062,13 @@
             }
 
             InvocationPluginAssertions assertions = Assertions.assertionsEnabled() ? new InvocationPluginAssertions(plugin, args, targetMethod, resultType) : null;
-            if (plugin.execute(this, targetMethod, pluginReceiver, args)) {
-                afterInvocationPluginExecution(true, assertions, intrinsicGuard, invokeKind, args, targetMethod, resultType, returnType);
-                return true;
-            } else {
-                afterInvocationPluginExecution(false, assertions, intrinsicGuard, invokeKind, args, targetMethod, resultType, returnType);
+            try (DebugCloseable context = openNodeContext(targetMethod)) {
+                if (plugin.execute(this, targetMethod, pluginReceiver, args)) {
+                    afterInvocationPluginExecution(true, assertions, intrinsicGuard, invokeKind, args, targetMethod, resultType, returnType);
+                    return true;
+                } else {
+                    afterInvocationPluginExecution(false, assertions, intrinsicGuard, invokeKind, args, targetMethod, resultType, returnType);
+                }
             }
         }
         return false;
@@ -2112,6 +2135,7 @@
      * Tries to inline {@code targetMethod} if it is an instance field accessor. This avoids the
      * overhead of creating and using a nested {@link BytecodeParser} object.
      */
+    @SuppressWarnings("try")
     private boolean tryFastInlineAccessor(ValueNode[] args, ResolvedJavaMethod targetMethod) {
         byte[] bytecode = targetMethod.getCode();
         if (bytecode != null && bytecode.length == ACCESSOR_BYTECODE_LENGTH &&
@@ -2124,10 +2148,12 @@
                 if (field instanceof ResolvedJavaField) {
                     ValueNode receiver = invocationPluginReceiver.init(targetMethod, args).get();
                     ResolvedJavaField resolvedField = (ResolvedJavaField) field;
-                    genGetField(resolvedField, receiver);
-                    notifyBeforeInline(targetMethod);
-                    printInlining(targetMethod, targetMethod, true, "inline accessor method (bytecode parsing)");
-                    notifyAfterInline(targetMethod);
+                    try (DebugCloseable context = openNodeContext(targetMethod, 1)) {
+                        genGetField(resolvedField, receiver);
+                        notifyBeforeInline(targetMethod);
+                        printInlining(targetMethod, targetMethod, true, "inline accessor method (bytecode parsing)");
+                        notifyAfterInline(targetMethod);
+                    }
                     return true;
                 }
             }
@@ -2562,6 +2588,7 @@
 
     @Override
     public <T extends ValueNode> T append(T v) {
+        assert !graph.trackNodeSourcePosition() || graph.currentNodeSourcePosition() != null || currentBlock == blockMap.getUnwindBlock() || currentBlock instanceof ExceptionDispatchBlock;
         if (v.graph() != null) {
             return v;
         }
@@ -2670,93 +2697,97 @@
         return createTarget(block, state, false, false);
     }
 
+    @SuppressWarnings("try")
     private FixedNode createTarget(BciBlock block, FrameStateBuilder state, boolean canReuseInstruction, boolean canReuseState) {
         assert block != null && state != null;
         assert !block.isExceptionEntry || state.stackSize() == 1;
 
-        if (getFirstInstruction(block) == null) {
-            /*
-             * This is the first time we see this block as a branch target. Create and return a
-             * placeholder that later can be replaced with a MergeNode when we see this block again.
-             */
-            FixedNode targetNode;
-            if (canReuseInstruction && (block.getPredecessorCount() == 1 || !controlFlowSplit) && !block.isLoopHeader && (currentBlock.loops & ~block.loops) == 0) {
-                setFirstInstruction(block, lastInstr);
-                lastInstr = null;
-            } else {
-                setFirstInstruction(block, graph.add(new BeginNode()));
+        try (DebugCloseable context = openNodeContext(state, block.startBci)) {
+            if (getFirstInstruction(block) == null) {
+                /*
+                 * This is the first time we see this block as a branch target. Create and return a
+                 * placeholder that later can be replaced with a MergeNode when we see this block
+                 * again.
+                 */
+                FixedNode targetNode;
+                if (canReuseInstruction && (block.getPredecessorCount() == 1 || !controlFlowSplit) && !block.isLoopHeader && (currentBlock.loops & ~block.loops) == 0) {
+                    setFirstInstruction(block, lastInstr);
+                    lastInstr = null;
+                } else {
+                    setFirstInstruction(block, graph.add(new BeginNode()));
+                }
+                targetNode = getFirstInstruction(block);
+                Target target = checkLoopExit(targetNode, block, state);
+                FixedNode result = target.fixed;
+                FrameStateBuilder currentEntryState = target.state == state ? (canReuseState ? state : state.copy()) : target.state;
+                setEntryState(block, currentEntryState);
+                currentEntryState.clearNonLiveLocals(block, liveness, true);
+
+                debug.log("createTarget %s: first visit, result: %s", block, targetNode);
+                return result;
             }
-            targetNode = getFirstInstruction(block);
-            Target target = checkLoopExit(targetNode, block, state);
+
+            // We already saw this block before, so we have to merge states.
+            if (!getEntryState(block).isCompatibleWith(state)) {
+                throw bailout("stacks do not match; bytecodes would not verify");
+            }
+
+            if (getFirstInstruction(block) instanceof LoopBeginNode) {
+                assert (block.isLoopHeader && currentBlock.getId() >= block.getId()) : "must be backward branch";
+                /*
+                 * Backward loop edge. We need to create a special LoopEndNode and merge with the
+                 * loop begin node created before.
+                 */
+                LoopBeginNode loopBegin = (LoopBeginNode) getFirstInstruction(block);
+                LoopEndNode loopEnd = graph.add(new LoopEndNode(loopBegin));
+                Target target = checkLoopExit(loopEnd, block, state);
+                FixedNode result = target.fixed;
+                getEntryState(block).merge(loopBegin, target.state);
+
+                debug.log("createTarget %s: merging backward branch to loop header %s, result: %s", block, loopBegin, result);
+                return result;
+            }
+            assert currentBlock == null || currentBlock.getId() < block.getId() : "must not be backward branch";
+            assert getFirstInstruction(block).next() == null : "bytecodes already parsed for block";
+
+            if (getFirstInstruction(block) instanceof AbstractBeginNode && !(getFirstInstruction(block) instanceof AbstractMergeNode)) {
+                /*
+                 * This is the second time we see this block. Create the actual MergeNode and the
+                 * End Node for the already existing edge.
+                 */
+                AbstractBeginNode beginNode = (AbstractBeginNode) getFirstInstruction(block);
+
+                // The EndNode for the already existing edge.
+                EndNode end = graph.add(new EndNode());
+                // The MergeNode that replaces the placeholder.
+                AbstractMergeNode mergeNode = graph.add(new MergeNode());
+                FixedNode next = beginNode.next();
+
+                if (beginNode.predecessor() instanceof ControlSplitNode) {
+                    beginNode.setNext(end);
+                } else {
+                    beginNode.replaceAtPredecessor(end);
+                    beginNode.safeDelete();
+                }
+
+                mergeNode.addForwardEnd(end);
+                mergeNode.setNext(next);
+
+                setFirstInstruction(block, mergeNode);
+            }
+
+            AbstractMergeNode mergeNode = (AbstractMergeNode) getFirstInstruction(block);
+
+            // The EndNode for the newly merged edge.
+            EndNode newEnd = graph.add(new EndNode());
+            Target target = checkLoopExit(newEnd, block, state);
             FixedNode result = target.fixed;
-            FrameStateBuilder currentEntryState = target.state == state ? (canReuseState ? state : state.copy()) : target.state;
-            setEntryState(block, currentEntryState);
-            currentEntryState.clearNonLiveLocals(block, liveness, true);
-
-            debug.log("createTarget %s: first visit, result: %s", block, targetNode);
+            getEntryState(block).merge(mergeNode, target.state);
+            mergeNode.addForwardEnd(newEnd);
+
+            debug.log("createTarget %s: merging state, result: %s", block, result);
             return result;
         }
-
-        // We already saw this block before, so we have to merge states.
-        if (!getEntryState(block).isCompatibleWith(state)) {
-            throw bailout("stacks do not match; bytecodes would not verify");
-        }
-
-        if (getFirstInstruction(block) instanceof LoopBeginNode) {
-            assert (block.isLoopHeader && currentBlock.getId() >= block.getId()) : "must be backward branch";
-            /*
-             * Backward loop edge. We need to create a special LoopEndNode and merge with the loop
-             * begin node created before.
-             */
-            LoopBeginNode loopBegin = (LoopBeginNode) getFirstInstruction(block);
-            LoopEndNode loopEnd = graph.add(new LoopEndNode(loopBegin));
-            Target target = checkLoopExit(loopEnd, block, state);
-            FixedNode result = target.fixed;
-            getEntryState(block).merge(loopBegin, target.state);
-
-            debug.log("createTarget %s: merging backward branch to loop header %s, result: %s", block, loopBegin, result);
-            return result;
-        }
-        assert currentBlock == null || currentBlock.getId() < block.getId() : "must not be backward branch";
-        assert getFirstInstruction(block).next() == null : "bytecodes already parsed for block";
-
-        if (getFirstInstruction(block) instanceof AbstractBeginNode && !(getFirstInstruction(block) instanceof AbstractMergeNode)) {
-            /*
-             * This is the second time we see this block. Create the actual MergeNode and the End
-             * Node for the already existing edge.
-             */
-            AbstractBeginNode beginNode = (AbstractBeginNode) getFirstInstruction(block);
-
-            // The EndNode for the already existing edge.
-            EndNode end = graph.add(new EndNode());
-            // The MergeNode that replaces the placeholder.
-            AbstractMergeNode mergeNode = graph.add(new MergeNode());
-            FixedNode next = beginNode.next();
-
-            if (beginNode.predecessor() instanceof ControlSplitNode) {
-                beginNode.setNext(end);
-            } else {
-                beginNode.replaceAtPredecessor(end);
-                beginNode.safeDelete();
-            }
-
-            mergeNode.addForwardEnd(end);
-            mergeNode.setNext(next);
-
-            setFirstInstruction(block, mergeNode);
-        }
-
-        AbstractMergeNode mergeNode = (AbstractMergeNode) getFirstInstruction(block);
-
-        // The EndNode for the newly merged edge.
-        EndNode newEnd = graph.add(new EndNode());
-        Target target = checkLoopExit(newEnd, block, state);
-        FixedNode result = target.fixed;
-        getEntryState(block).merge(mergeNode, target.state);
-        mergeNode.addForwardEnd(newEnd);
-
-        debug.log("createTarget %s: merging state, result: %s", block, result);
-        return result;
     }
 
     /**
@@ -2965,28 +2996,28 @@
         }
 
         while (bci < endBCI) {
-            if (graphBuilderConfig.insertFullInfopoints() && !parsingIntrinsic()) {
-                currentLineNumber = lnt != null ? lnt.getLineNumber(bci) : -1;
-                if (currentLineNumber != previousLineNumber) {
-                    genInfoPointNode(InfopointReason.BYTECODE_POSITION, null);
-                    previousLineNumber = currentLineNumber;
+            try (DebugCloseable context = openNodeContext()) {
+                if (graphBuilderConfig.insertFullInfopoints() && !parsingIntrinsic()) {
+                    currentLineNumber = lnt != null ? lnt.getLineNumber(bci) : -1;
+                    if (currentLineNumber != previousLineNumber) {
+                        genInfoPointNode(InfopointReason.BYTECODE_POSITION, null);
+                        previousLineNumber = currentLineNumber;
+                    }
                 }
-            }
-
-            // read the opcode
-            int opcode = stream.currentBC();
-            assert traceState();
-            assert traceInstruction(bci, opcode, bci == block.startBci);
-            if (parent == null && bci == entryBCI) {
-                if (block.getJsrScope() != JsrScope.EMPTY_SCOPE) {
-                    throw new JsrNotSupportedBailout("OSR into a JSR scope is not supported");
+
+                // read the opcode
+                int opcode = stream.currentBC();
+                assert traceState();
+                assert traceInstruction(bci, opcode, bci == block.startBci);
+                if (parent == null && bci == entryBCI) {
+                    if (block.getJsrScope() != JsrScope.EMPTY_SCOPE) {
+                        throw new JsrNotSupportedBailout("OSR into a JSR scope is not supported");
+                    }
+                    EntryMarkerNode x = append(new EntryMarkerNode());
+                    frameState.insertProxies(value -> graph.unique(new EntryProxyNode(value, x)));
+                    x.setStateAfter(createFrameState(bci, x));
                 }
-                EntryMarkerNode x = append(new EntryMarkerNode());
-                frameState.insertProxies(value -> graph.unique(new EntryProxyNode(value, x)));
-                x.setStateAfter(createFrameState(bci, x));
-            }
-
-            try (DebugCloseable context = openNodeContext()) {
+
                 processBytecode(bci, opcode);
             } catch (BailoutException e) {
                 // Don't wrap bailouts as parser errors
@@ -3017,11 +3048,26 @@
         }
     }
 
+    private DebugCloseable openNodeContext(FrameStateBuilder state, int startBci) {
+        if (graph.trackNodeSourcePosition()) {
+            return graph.withNodeSourcePosition(state.createBytecodePosition(startBci));
+        }
+        return null;
+    }
+
+    private DebugCloseable openNodeContext(ResolvedJavaMethod targetMethod) {
+        return openNodeContext(targetMethod, -1);
+    }
+
+    private DebugCloseable openNodeContext(ResolvedJavaMethod targetMethod, int bci) {
+        if (graph.trackNodeSourcePosition()) {
+            return graph.withNodeSourcePosition(new NodeSourcePosition(createBytecodePosition(), targetMethod, bci));
+        }
+        return null;
+    }
+
     private DebugCloseable openNodeContext() {
-        if ((graphBuilderConfig.trackNodeSourcePosition() || debug.isDumpEnabledForMethod()) && !parsingIntrinsic()) {
-            return graph.withNodeSourcePosition(createBytecodePosition());
-        }
-        return null;
+        return openNodeContext(frameState, bci());
     }
 
     /* Also a hook for subclasses. */
@@ -3133,7 +3179,7 @@
         genIf(condition, trueSuccessor, falseSuccessor, probability);
     }
 
-    private double getProfileProbability(boolean negate) {
+    protected double getProfileProbability(boolean negate) {
         double probability;
         if (profilingInfo == null) {
             probability = 0.5;
@@ -3433,7 +3479,8 @@
     }
 
     protected NodeSourcePosition createBytecodePosition() {
-        return frameState.createBytecodePosition(bci());
+        NodeSourcePosition bytecodePosition = frameState.createBytecodePosition(bci());
+        return bytecodePosition;
     }
 
     public void setCurrentFrameState(FrameStateBuilder frameState) {
@@ -3454,6 +3501,7 @@
         frameState.push(kind, value);
     }
 
+    @SuppressWarnings("try")
     public void loadLocalObject(int index) {
         ValueNode value = frameState.loadLocal(index, JavaKind.Object);
 
@@ -3461,7 +3509,9 @@
         int nextBC = stream.readUByte(nextBCI);
         if (nextBCI <= currentBlock.endBci && nextBC == Bytecodes.GETFIELD) {
             stream.next();
-            genGetField(stream.readCPI(), Bytecodes.GETFIELD, value);
+            try (DebugCloseable ignored = openNodeContext()) {
+                genGetField(stream.readCPI(), Bytecodes.GETFIELD, value);
+            }
         } else {
             frameState.push(JavaKind.Object, value);
         }
@@ -3689,6 +3739,17 @@
         genIf(x, cond, y);
     }
 
+    private static void initialize(ResolvedJavaType resolvedType) {
+        /*
+         * Since we're potentially triggering class initialization here, we need synchronization to
+         * mitigate the potential for class initialization related deadlock being caused by the
+         * compiler (e.g., https://github.com/graalvm/graal-core/pull/232/files#r90788550).
+         */
+        synchronized (BytecodeParser.class) {
+            resolvedType.initialize();
+        }
+    }
+
     protected JavaType lookupType(int cpi, int bytecode) {
         maybeEagerlyResolve(cpi, bytecode);
         JavaType result = constantPool.lookupType(cpi, bytecode);
@@ -3699,32 +3760,26 @@
     private JavaMethod lookupMethod(int cpi, int opcode) {
         maybeEagerlyResolve(cpi, opcode);
         JavaMethod result = constantPool.lookupMethod(cpi, opcode);
-        /*
-         * In general, one cannot assume that the declaring class being initialized is useful, since
-         * the actual concrete receiver may be a different class (except for static calls). Also,
-         * interfaces are initialized only under special circumstances, so that this assertion would
-         * often fail for interface calls.
-         */
-        assert !graphBuilderConfig.unresolvedIsError() ||
-                        (result instanceof ResolvedJavaMethod && (opcode != INVOKESTATIC || ((ResolvedJavaMethod) result).getDeclaringClass().isInitialized())) : result;
+        assert !graphBuilderConfig.unresolvedIsError() || result instanceof ResolvedJavaMethod : result;
         return result;
     }
 
     protected JavaField lookupField(int cpi, int opcode) {
         maybeEagerlyResolve(cpi, opcode);
         JavaField result = constantPool.lookupField(cpi, method, opcode);
-
-        if (graphBuilderConfig.eagerResolving()) {
-            assert !graphBuilderConfig.unresolvedIsError() || result instanceof ResolvedJavaField : "Not resolved: " + result;
+        assert !graphBuilderConfig.unresolvedIsError() || result instanceof ResolvedJavaField : "Not resolved: " + result;
+        if (parsingIntrinsic() || eagerInitializing) {
             if (result instanceof ResolvedJavaField) {
                 ResolvedJavaType declaringClass = ((ResolvedJavaField) result).getDeclaringClass();
                 if (!declaringClass.isInitialized()) {
-                    assert declaringClass.isInterface() : "Declaring class not initialized but not an interface? " + declaringClass;
-                    declaringClass.initialize();
+                    // Even with eager initialization, superinterfaces are not always initialized.
+                    // See StaticInterfaceFieldTest
+                    assert !eagerInitializing || declaringClass.isInterface() : "Declaring class not initialized but not an interface? " + declaringClass;
+                    initialize(declaringClass);
                 }
             }
         }
-        assert !graphBuilderConfig.unresolvedIsError() || (result instanceof ResolvedJavaField && ((ResolvedJavaField) result).getDeclaringClass().isInitialized()) : result;
+        assert !uninitializedIsError || (result instanceof ResolvedJavaField && ((ResolvedJavaField) result).getDeclaringClass().isInitialized()) : result;
         return result;
     }
 
@@ -3745,7 +3800,12 @@
              * the compiler (e.g., https://github.com/graalvm/graal-core/pull/232/files#r90788550).
              */
             synchronized (BytecodeParser.class) {
-                constantPool.loadReferencedType(cpi, bytecode);
+                ClassInitializationPlugin classInitializationPlugin = graphBuilderConfig.getPlugins().getClassInitializationPlugin();
+                if (classInitializationPlugin != null) {
+                    classInitializationPlugin.loadReferencedType(this, constantPool, cpi, bytecode);
+                } else {
+                    constantPool.loadReferencedType(cpi, bytecode);
+                }
             }
         }
     }
@@ -3872,11 +3932,16 @@
     }
 
     void genNewInstance(JavaType type) {
-        if (!(type instanceof ResolvedJavaType) || !((ResolvedJavaType) type).isInitialized()) {
+        if (!(type instanceof ResolvedJavaType)) {
             handleUnresolvedNewInstance(type);
             return;
         }
         ResolvedJavaType resolvedType = (ResolvedJavaType) type;
+        ClassInitializationPlugin classInitializationPlugin = graphBuilderConfig.getPlugins().getClassInitializationPlugin();
+        if (!resolvedType.isInitialized() && classInitializationPlugin == null) {
+            handleUnresolvedNewInstance(type);
+            return;
+        }
 
         ResolvedJavaType[] skippedExceptionTypes = this.graphBuilderConfig.getSkippedExceptionTypes();
         if (skippedExceptionTypes != null) {
@@ -3888,7 +3953,6 @@
             }
         }
 
-        ClassInitializationPlugin classInitializationPlugin = graphBuilderConfig.getPlugins().getClassInitializationPlugin();
         if (classInitializationPlugin != null && classInitializationPlugin.shouldApply(this, resolvedType)) {
             FrameState stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null);
             classInitializationPlugin.apply(this, resolvedType, stateBefore);
@@ -4078,7 +4142,7 @@
         }
     }
 
-    private boolean needsExplicitException() {
+    protected boolean needsExplicitException() {
         BytecodeExceptionMode exceptionMode = graphBuilderConfig.getBytecodeExceptionMode();
         if (exceptionMode == BytecodeExceptionMode.CheckAll || StressExplicitExceptionCode.getValue(options)) {
             return true;
@@ -4163,7 +4227,7 @@
     private ResolvedJavaField resolveStaticFieldAccess(JavaField field, ValueNode value) {
         if (field instanceof ResolvedJavaField) {
             ResolvedJavaField resolvedField = (ResolvedJavaField) field;
-            if (resolvedField.getDeclaringClass().isInitialized()) {
+            if (resolvedField.getDeclaringClass().isInitialized() || graphBuilderConfig.getPlugins().getClassInitializationPlugin() != null) {
                 return resolvedField;
             }
             /*
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParserOptions.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParserOptions.java	Fri Mar 16 22:59:32 2018 -0700
@@ -58,7 +58,7 @@
     public static final OptionKey<Boolean> TraceParserPlugins = new OptionKey<>(false);
 
     @Option(help = "Maximum depth when inlining during bytecode parsing.", type = OptionType.Debug)
-    public static final OptionKey<Integer> InlineDuringParsingMaxDepth = new OptionKey<>(3);
+    public static final OptionKey<Integer> InlineDuringParsingMaxDepth = new OptionKey<>(10);
 
     @Option(help = "When creating info points hide the methods of the substitutions.", type = OptionType.Debug)
     public static final OptionKey<Boolean> HideSubstitutionStates = new OptionKey<>(false);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java	Fri Mar 16 22:59:32 2018 -0700
@@ -32,7 +32,6 @@
 import static org.graalvm.compiler.bytecode.Bytecodes.POP2;
 import static org.graalvm.compiler.bytecode.Bytecodes.SWAP;
 import static org.graalvm.compiler.debug.GraalError.shouldNotReachHere;
-import static org.graalvm.compiler.java.BytecodeParserOptions.HideSubstitutionStates;
 import static org.graalvm.compiler.nodes.FrameState.TWO_SLOT_MARKER;
 
 import java.util.ArrayList;
@@ -74,7 +73,6 @@
 
 import jdk.vm.ci.code.BytecodeFrame;
 import jdk.vm.ci.meta.Assumptions;
-import jdk.vm.ci.meta.JavaConstant;
 import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.JavaType;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
@@ -112,8 +110,6 @@
      */
     private List<StateSplit> sideEffects;
 
-    private JavaConstant constantReceiver;
-
     /**
      * Creates a new frame state builder for the given method and the given target graph.
      *
@@ -164,7 +160,6 @@
             locals[javaIndex] = arguments[index];
             javaIndex = 1;
             index = 1;
-            constantReceiver = locals[0].asJavaConstant();
         }
         Signature sig = getMethod().getSignature();
         int max = sig.getParameterCount(false);
@@ -310,7 +305,7 @@
 
     public FrameState create(int bci, StateSplit forStateSplit) {
         if (parser != null && parser.parsingIntrinsic()) {
-            NodeSourcePosition sourcePosition = createBytecodePosition(bci, false);
+            NodeSourcePosition sourcePosition = parser.getGraph().trackNodeSourcePosition() ? createBytecodePosition(bci) : null;
             return parser.intrinsicContext.createFrameState(parser.getGraph(), this, forStateSplit, sourcePosition);
         }
 
@@ -354,25 +349,14 @@
     }
 
     public NodeSourcePosition createBytecodePosition(int bci) {
-        return createBytecodePosition(bci, HideSubstitutionStates.getValue(parser.graph.getOptions()));
+        BytecodeParser parent = parser.getParent();
+        NodeSourcePosition position = create(bci, parent);
+        return position;
     }
 
-    private NodeSourcePosition createBytecodePosition(int bci, boolean hideSubstitutionStates) {
-        BytecodeParser parent = parser.getParent();
-        if (hideSubstitutionStates) {
-            if (parser.parsingIntrinsic()) {
-                // Attribute to the method being replaced
-                return new NodeSourcePosition(constantReceiver, parent.getFrameStateBuilder().createBytecodePosition(parent.bci()), parser.intrinsicContext.getOriginalMethod(), -1);
-            }
-            // Skip intrinsic frames
-            parent = parser.getNonIntrinsicAncestor();
-        }
-        return create(constantReceiver, bci, parent, hideSubstitutionStates);
-    }
-
-    private NodeSourcePosition create(JavaConstant receiver, int bci, BytecodeParser parent, boolean hideSubstitutionStates) {
+    private NodeSourcePosition create(int bci, BytecodeParser parent) {
         if (outerSourcePosition == null && parent != null) {
-            outerSourcePosition = parent.getFrameStateBuilder().createBytecodePosition(parent.bci(), hideSubstitutionStates);
+            outerSourcePosition = parent.getFrameStateBuilder().createBytecodePosition(parent.bci());
         }
         if (bci == BytecodeFrame.AFTER_EXCEPTION_BCI && parent != null) {
             return FrameState.toSourcePosition(outerFrameState);
@@ -380,7 +364,7 @@
         if (bci == BytecodeFrame.INVALID_FRAMESTATE_BCI) {
             throw shouldNotReachHere();
         }
-        return new NodeSourcePosition(receiver, outerSourcePosition, code.getMethod(), bci);
+        return new NodeSourcePosition(outerSourcePosition, code.getMethod(), bci);
     }
 
     public FrameStateBuilder copy() {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/JTTTest.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/JTTTest.java	Fri Mar 16 22:59:32 2018 -0700
@@ -22,25 +22,14 @@
  */
 package org.graalvm.compiler.jtt;
 
-import static java.lang.reflect.Modifier.isStatic;
-
 import java.util.Collections;
 import java.util.Set;
 
 import org.graalvm.compiler.core.test.GraalCompilerTest;
-import org.graalvm.compiler.nodes.ConstantNode;
-import org.graalvm.compiler.nodes.ParameterNode;
-import org.graalvm.compiler.nodes.StructuredGraph;
-import org.graalvm.compiler.nodes.StructuredGraph.Builder;
 import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.compiler.phases.PhaseSuite;
-import org.graalvm.compiler.phases.tiers.HighTierContext;
 import org.junit.Assert;
 
-import jdk.vm.ci.code.InstalledCode;
 import jdk.vm.ci.meta.DeoptimizationReason;
-import jdk.vm.ci.meta.JavaConstant;
-import jdk.vm.ci.meta.JavaType;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 
 /**
@@ -66,45 +55,35 @@
     }
 
     @Override
-    protected StructuredGraph parse(Builder builder, PhaseSuite<HighTierContext> graphBuilderSuite) {
-        StructuredGraph graph = super.parse(builder, graphBuilderSuite);
-        if (argsToBind != null) {
-            ResolvedJavaMethod m = graph.method();
-            Object receiver = isStatic(m.getModifiers()) ? null : this;
-            Object[] args = argsWithReceiver(receiver, argsToBind);
-            JavaType[] parameterTypes = m.toParameterTypes();
-            assert parameterTypes.length == args.length;
-            for (ParameterNode param : graph.getNodes(ParameterNode.TYPE)) {
-                JavaConstant c = getSnippetReflection().forBoxed(parameterTypes[param.index()].getJavaKind(), args[param.index()]);
-                ConstantNode replacement = ConstantNode.forConstant(c, getMetaAccess(), graph);
-                param.replaceAtUsages(replacement);
-            }
-        }
-        return graph;
+    protected Object[] getArgumentToBind() {
+        return argsToBind;
     }
 
-    @Override
-    protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph graph, boolean forceCompile, boolean installAsDefault, OptionValues options) {
-        return super.getCode(method, graph, argsToBind != null, installAsDefault, options);
-    }
-
-    Double delta;
+    /**
+     * If non-null, then this is a test for a method returning a {@code double} value that must be
+     * within {@code ulpDelta}s of the expected value.
+     */
+    protected Double ulpDelta;
 
     @Override
     protected void assertDeepEquals(Object expected, Object actual) {
-        if (delta != null) {
-            Assert.assertEquals(((Number) expected).doubleValue(), ((Number) actual).doubleValue(), delta);
+        if (ulpDelta != null) {
+            double expectedDouble = (double) expected;
+            double actualDouble = (Double) actual;
+            double ulp = Math.ulp(expectedDouble);
+            double delta = ulpDelta * ulp;
+            try {
+                Assert.assertEquals(expectedDouble, actualDouble, delta);
+            } catch (AssertionError e) {
+                double diff = Math.abs(expectedDouble - actualDouble);
+                double diffUlps = diff / ulp;
+                throw new AssertionError(e.getMessage() + " // " + diffUlps + " ulps");
+            }
         } else {
             super.assertDeepEquals(expected, actual);
         }
     }
 
-    @SuppressWarnings("hiding")
-    protected void runTestWithDelta(double delta, String name, Object... args) {
-        this.delta = Double.valueOf(delta);
-        runTest(name, args);
-    }
-
     protected void runTest(String name, Object... args) {
         runTest(getInitialOptions(), name, args);
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotpath/HP_series.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotpath/HP_series.java	Fri Mar 16 22:59:32 2018 -0700
@@ -24,11 +24,9 @@
 
 package org.graalvm.compiler.jtt.hotpath;
 
-import org.junit.Ignore;
+import org.graalvm.compiler.jtt.JTTTest;
 import org.junit.Test;
 
-import org.graalvm.compiler.jtt.JTTTest;
-
 /*
  */
 public class HP_series extends JTTTest {
@@ -101,17 +99,16 @@
         return (0.0);
     }
 
-    /*
-     * This test is sensible to the implementation of Math.pow, cos and sin. Since for these
-     * functions, the specs says "The computed result must be within 1 ulp of the exact result",
-     * different implementation may return different results. The 11 ulp delta allowed for test(100)
-     * tries to account for that but is not guaranteed to work forever.
+    /**
+     * This test is sensitive to the implementation of {@link Math#pow}, {@link Math#cos} and
+     * {@link Math#sin(double)}. Since for these functions, the specs says "The computed result must
+     * be within 1 ulp of the exact result", different implementation may return different results.
+     * The 11 ulp delta allowed for test(100) tries to account for that but is not guaranteed to
+     * work forever.
      */
-    @Ignore("failure-prone because of the variabiliy of pow/cos/sin")
     @Test
     public void run0() throws Throwable {
-        double expected = 0.6248571921291398d;
-        runTestWithDelta(11 * Math.ulp(expected), "test", 100);
+        ulpDelta = 11.0D;
+        runTest("test", 100);
     }
-
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/Math_abs.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/Math_abs.java	Fri Mar 16 22:59:32 2018 -0700
@@ -22,13 +22,14 @@
  */
 package org.graalvm.compiler.jtt.lang;
 
+import org.graalvm.compiler.options.OptionValues;
 import org.junit.Test;
 
-import org.graalvm.compiler.jtt.JTTTest;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
 
 /*
  */
-public class Math_abs extends JTTTest {
+public class Math_abs extends UnaryMath {
 
     @SuppressWarnings("serial")
     public static class NaN extends Throwable {
@@ -78,4 +79,10 @@
         runTest("test", java.lang.Double.NaN);
     }
 
+    @Test
+    public void run7() {
+        OptionValues options = getInitialOptions();
+        ResolvedJavaMethod method = getResolvedJavaMethod("test");
+        testManyValues(options, method);
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/Math_cos.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/Math_cos.java	Fri Mar 16 22:59:32 2018 -0700
@@ -22,13 +22,14 @@
  */
 package org.graalvm.compiler.jtt.lang;
 
+import org.graalvm.compiler.options.OptionValues;
 import org.junit.Test;
 
-import org.graalvm.compiler.jtt.JTTTest;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
 
 /*
  */
-public class Math_cos extends JTTTest {
+public class Math_cos extends UnaryMath {
 
     @SuppressWarnings("serial")
     public static class NaN extends Throwable {
@@ -58,4 +59,10 @@
         runTest("test", java.lang.Double.POSITIVE_INFINITY);
     }
 
+    @Test
+    public void run3() {
+        OptionValues options = getInitialOptions();
+        ResolvedJavaMethod method = getResolvedJavaMethod("test");
+        testManyValues(options, method);
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/Math_exp.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/Math_exp.java	Fri Mar 16 22:59:32 2018 -0700
@@ -22,14 +22,12 @@
  */
 package org.graalvm.compiler.jtt.lang;
 
-import org.junit.Ignore;
+import org.graalvm.compiler.options.OptionValues;
 import org.junit.Test;
 
-import org.graalvm.compiler.jtt.JTTTest;
-
 /*
  */
-public class Math_exp extends JTTTest {
+public class Math_exp extends UnaryMath {
 
     public static double test(double arg) {
         return Math.exp(arg);
@@ -65,9 +63,19 @@
         runTest("test", 0.0D);
     }
 
-    @Ignore("java.lang.AssertionError: expected:<2.718281828459045> but was:<2.7182818284590455>")
     @Test
     public void run6() {
         runTest("test", 1.0D);
     }
+
+    @Test
+    public void run7() {
+        runTest("test", -1024D);
+    }
+
+    @Test
+    public void run8() {
+        OptionValues options = getInitialOptions();
+        testManyValues(options, getResolvedJavaMethod("test"));
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/Math_log.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/Math_log.java	Fri Mar 16 22:59:32 2018 -0700
@@ -22,13 +22,14 @@
  */
 package org.graalvm.compiler.jtt.lang;
 
+import org.graalvm.compiler.options.OptionValues;
 import org.junit.Test;
 
-import org.graalvm.compiler.jtt.JTTTest;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
 
 /*
  */
-public class Math_log extends JTTTest {
+public class Math_log extends UnaryMath {
 
     @SuppressWarnings("serial")
     public static class NaN extends Throwable {
@@ -78,4 +79,10 @@
         runTest("test", -0.0d);
     }
 
+    @Test
+    public void run7() {
+        OptionValues options = getInitialOptions();
+        ResolvedJavaMethod method = getResolvedJavaMethod("test");
+        testManyValues(options, method);
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/Math_pow.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/Math_pow.java	Fri Mar 16 22:59:32 2018 -0700
@@ -22,9 +22,11 @@
  */
 package org.graalvm.compiler.jtt.lang;
 
+import org.graalvm.compiler.jtt.JTTTest;
+import org.graalvm.compiler.options.OptionValues;
 import org.junit.Test;
 
-import org.graalvm.compiler.jtt.JTTTest;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
 
 /*
  */
@@ -88,4 +90,44 @@
     public void run10() throws Throwable {
         runTest("test", 0.999998, 1500000.0);
     }
+
+    private static final long STEP = Long.MAX_VALUE / 1_000_000;
+
+    @Test
+    public void run11() {
+        OptionValues options = getInitialOptions();
+        ResolvedJavaMethod method = getResolvedJavaMethod("test");
+        Object receiver = null;
+        long testIteration = 0;
+        for (long l = Long.MIN_VALUE;; l += STEP) {
+            double x = Double.longBitsToDouble(l);
+            double y = x;
+            testOne(options, method, receiver, testIteration, l, x, y);
+            y = l < 0 ? Double.longBitsToDouble(Long.MAX_VALUE + l) : Double.longBitsToDouble(Long.MAX_VALUE - l);
+            testOne(options, method, receiver, testIteration, l, x, y);
+            if (Long.MAX_VALUE - STEP < l) {
+                break;
+            }
+            testIteration++;
+        }
+    }
+
+    @Test
+    public void run12() {
+        long l = 4355599093822972882L;
+        double x = Double.longBitsToDouble(l);
+        OptionValues options = getInitialOptions();
+        ResolvedJavaMethod method = getResolvedJavaMethod("test");
+        Object receiver = null;
+        testOne(options, method, receiver, 1, l, x, x);
+    }
+
+    private void testOne(OptionValues options, ResolvedJavaMethod method, Object receiver, long testIteration, long l, double x, double y) throws AssertionError {
+        Result expect = executeExpected(method, receiver, x, y);
+        try {
+            testAgainstExpected(options, method, expect, EMPTY, receiver, x, y);
+        } catch (AssertionError e) {
+            throw new AssertionError(String.format("%d: While testing %g [long: %d, hex: %x]", testIteration, x, l, l), e);
+        }
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/Math_sin.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/Math_sin.java	Fri Mar 16 22:59:32 2018 -0700
@@ -22,13 +22,14 @@
  */
 package org.graalvm.compiler.jtt.lang;
 
+import org.graalvm.compiler.options.OptionValues;
 import org.junit.Test;
 
-import org.graalvm.compiler.jtt.JTTTest;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
 
 /*
  */
-public class Math_sin extends JTTTest {
+public class Math_sin extends UnaryMath {
 
     @SuppressWarnings("serial")
     public static class NaN extends Throwable {
@@ -83,4 +84,10 @@
         runTest("test", 0.0d);
     }
 
+    @Test
+    public void run5() {
+        OptionValues options = getInitialOptions();
+        ResolvedJavaMethod method = getResolvedJavaMethod("test");
+        testManyValues(options, method);
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/Math_sqrt.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/Math_sqrt.java	Fri Mar 16 22:59:32 2018 -0700
@@ -22,13 +22,14 @@
  */
 package org.graalvm.compiler.jtt.lang;
 
+import org.graalvm.compiler.options.OptionValues;
 import org.junit.Test;
 
-import org.graalvm.compiler.jtt.JTTTest;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
 
 /*
  */
-public class Math_sqrt extends JTTTest {
+public class Math_sqrt extends UnaryMath {
 
     @SuppressWarnings("serial")
     public static class NaN extends Throwable {
@@ -78,4 +79,10 @@
         runTest("test", -0.0d);
     }
 
+    @Test
+    public void run7() {
+        OptionValues options = getInitialOptions();
+        ResolvedJavaMethod method = getResolvedJavaMethod("test");
+        testManyValues(options, method);
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/Math_tan.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/Math_tan.java	Fri Mar 16 22:59:32 2018 -0700
@@ -22,13 +22,14 @@
  */
 package org.graalvm.compiler.jtt.lang;
 
+import org.graalvm.compiler.options.OptionValues;
 import org.junit.Test;
 
-import org.graalvm.compiler.jtt.JTTTest;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
 
 /*
  */
-public class Math_tan extends JTTTest {
+public class Math_tan extends UnaryMath {
 
     @SuppressWarnings("serial")
     public static class NaN extends Throwable {
@@ -68,4 +69,10 @@
         runTest("test", 0.0d);
     }
 
+    @Test
+    public void run5() {
+        OptionValues options = getInitialOptions();
+        ResolvedJavaMethod method = getResolvedJavaMethod("test");
+        testManyValues(options, method);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/UnaryMath.java	Fri Mar 16 22:59:32 2018 -0700
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.jtt.lang;
+
+import org.graalvm.compiler.jtt.JTTTest;
+import org.graalvm.compiler.options.OptionValues;
+
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
+public abstract class UnaryMath extends JTTTest {
+
+    private static final long STEP = Long.MAX_VALUE / 1_000_000;
+
+    /**
+     * Tests a unary {@link Math} method on a wide range of values.
+     */
+    void testManyValues(OptionValues options, ResolvedJavaMethod method) throws AssertionError {
+        if (!Java8OrEarlier) {
+            /*
+             * GR-8276: Allow for variance on JVMCI > 8 until a JVMCI version that includes
+             * https://github.com/graalvm/graal-jvmci-8/commit/
+             * c86fb66f86b8d52a08dd2495d34879d3730f9987 or Graal has stubs that a monotonic with
+             * other HotSpot implementations of these Math routines.
+             */
+            ulpDelta = 2D;
+        } else {
+            /*
+             * Forces the assertion message shows the ulps by which a computed result is wrong.
+             */
+            ulpDelta = 0D;
+        }
+        Object receiver = null;
+        long testIteration = 0;
+        for (long l = Long.MIN_VALUE;; l += STEP) {
+            double d = Double.longBitsToDouble(l);
+            Result expect = executeExpected(method, receiver, d);
+            try {
+                testAgainstExpected(options, method, expect, EMPTY, receiver, d);
+                testIteration++;
+            } catch (AssertionError e) {
+                throw new AssertionError(String.format("%d: While testing %g [long: %d, hex: %x]", testIteration, d, l, l), e);
+            }
+            if (Long.MAX_VALUE - STEP < l) {
+                break;
+            }
+        }
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Call.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Call.java	Fri Mar 16 22:59:32 2018 -0700
@@ -227,13 +227,15 @@
         masm.ensureUniquePC();
     }
 
-    public static void directJmp(CompilationResultBuilder crb, AArch64MacroAssembler masm, InvokeTarget target) {
-        int before = masm.position();
-        // Address is fixed up later by c++ code.
-        masm.jmp();
-        int after = masm.position();
-        crb.recordDirectCall(before, after, target, null);
-        masm.ensureUniquePC();
+    public static void directJmp(CompilationResultBuilder crb, AArch64MacroAssembler masm, InvokeTarget callTarget) {
+        try (AArch64MacroAssembler.ScratchRegister scratch = masm.getScratchRegister()) {
+            int before = masm.position();
+            masm.movNativeAddress(scratch.getRegister(), 0L);
+            masm.jmp(scratch.getRegister());
+            int after = masm.position();
+            crb.recordDirectCall(before, after, callTarget, null);
+            masm.ensureUniquePC();
+        }
     }
 
     public static void indirectJmp(CompilationResultBuilder crb, AArch64MacroAssembler masm, Register dst, InvokeTarget target) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayCompareToOp.java	Fri Mar 16 22:59:32 2018 -0700
@@ -0,0 +1,595 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.lir.amd64;
+
+import static jdk.vm.ci.amd64.AMD64.k7;
+import static jdk.vm.ci.amd64.AMD64.rax;
+import static jdk.vm.ci.amd64.AMD64.rcx;
+import static jdk.vm.ci.amd64.AMD64.rdx;
+import static jdk.vm.ci.code.ValueUtil.asRegister;
+import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL;
+import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.util.EnumSet;
+
+import org.graalvm.compiler.asm.Label;
+import org.graalvm.compiler.asm.amd64.AMD64Address;
+import org.graalvm.compiler.asm.amd64.AMD64Address.Scale;
+import org.graalvm.compiler.asm.amd64.AMD64Assembler.AvxVectorLen;
+import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag;
+import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
+import org.graalvm.compiler.core.common.LIRKind;
+import org.graalvm.compiler.lir.LIRInstructionClass;
+import org.graalvm.compiler.lir.Opcode;
+import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
+import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
+
+import jdk.vm.ci.amd64.AMD64;
+import jdk.vm.ci.amd64.AMD64.CPUFeature;
+import jdk.vm.ci.amd64.AMD64Kind;
+import jdk.vm.ci.code.Register;
+import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.Value;
+import sun.misc.Unsafe;
+
+/**
+ * Emits code which compares two arrays lexicographically. If the CPU supports any vector
+ * instructions specialized code is emitted to leverage these instructions.
+ */
+@Opcode("ARRAY_COMPARE_TO")
+public final class AMD64ArrayCompareToOp extends AMD64LIRInstruction {
+    public static final LIRInstructionClass<AMD64ArrayCompareToOp> TYPE = LIRInstructionClass.create(AMD64ArrayCompareToOp.class);
+
+    private final JavaKind kind1;
+    private final JavaKind kind2;
+    private final int array1BaseOffset;
+    private final int array2BaseOffset;
+
+    @Def({REG}) protected Value resultValue;
+    @Alive({REG}) protected Value array1Value;
+    @Alive({REG}) protected Value array2Value;
+    @Alive({REG}) protected Value length1Value;
+    @Alive({REG}) protected Value length2Value;
+    @Temp({REG}) protected Value temp1;
+    @Temp({REG}) protected Value temp2;
+
+    @Temp({REG, ILLEGAL}) protected Value vectorTemp1;
+
+    public AMD64ArrayCompareToOp(LIRGeneratorTool tool, JavaKind kind1, JavaKind kind2, Value result, Value array1, Value array2, Value length1, Value length2) {
+        super(TYPE);
+        this.kind1 = kind1;
+        this.kind2 = kind2;
+
+        // Both offsets should be the same but better be safe than sorry.
+        Class<?> array1Class = Array.newInstance(kind1.toJavaClass(), 0).getClass();
+        Class<?> array2Class = Array.newInstance(kind2.toJavaClass(), 0).getClass();
+        this.array1BaseOffset = UNSAFE.arrayBaseOffset(array1Class);
+        this.array2BaseOffset = UNSAFE.arrayBaseOffset(array2Class);
+
+        this.resultValue = result;
+        this.array1Value = array1;
+        this.array2Value = array2;
+        this.length1Value = length1;
+        this.length2Value = length2;
+
+        // Allocate some temporaries.
+        this.temp1 = tool.newVariable(LIRKind.unknownReference(tool.target().arch.getWordKind()));
+        this.temp2 = tool.newVariable(LIRKind.unknownReference(tool.target().arch.getWordKind()));
+
+        // We only need the vector temporaries if we generate SSE code.
+        if (supportsSSE42(tool.target())) {
+            this.vectorTemp1 = tool.newVariable(LIRKind.value(AMD64Kind.DOUBLE));
+        } else {
+            this.vectorTemp1 = Value.ILLEGAL;
+        }
+    }
+
+    private static boolean supportsSSE42(TargetDescription target) {
+        AMD64 arch = (AMD64) target.arch;
+        return arch.getFeatures().contains(CPUFeature.SSE4_2);
+    }
+
+    private static boolean supportsAVX2(TargetDescription target) {
+        AMD64 arch = (AMD64) target.arch;
+        return arch.getFeatures().contains(CPUFeature.AVX2);
+    }
+
+    private static boolean supportsAVX512VLBW(TargetDescription target) {
+        AMD64 arch = (AMD64) target.arch;
+        EnumSet<CPUFeature> features = arch.getFeatures();
+        return features.contains(CPUFeature.AVX512BW) && features.contains(CPUFeature.AVX512VL);
+    }
+
+    @Override
+    public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+        Register result = asRegister(resultValue);
+        Register str1 = asRegister(temp1);
+        Register str2 = asRegister(temp2);
+
+        // Load array base addresses.
+        masm.leaq(str1, new AMD64Address(asRegister(array1Value), array1BaseOffset));
+        masm.leaq(str2, new AMD64Address(asRegister(array2Value), array2BaseOffset));
+        Register cnt1 = asRegister(length1Value);
+        Register cnt2 = asRegister(length2Value);
+
+        // Checkstyle: stop
+        Label LENGTH_DIFF_LABEL = new Label();
+        Label POP_LABEL = new Label();
+        Label DONE_LABEL = new Label();
+        Label WHILE_HEAD_LABEL = new Label();
+        Label COMPARE_WIDE_VECTORS_LOOP_FAILED = new Label(); // used only _LP64 && AVX3
+        int stride, stride2;
+        int adr_stride = -1;
+        int adr_stride1 = -1;
+        int adr_stride2 = -1;
+        // Checkstyle: resume
+        int stride2x2 = 0x40;
+        AMD64Address.Scale scale = null;
+        AMD64Address.Scale scale1 = null;
+        AMD64Address.Scale scale2 = null;
+
+        // if (ae != StrIntrinsicNode::LL) {
+        if (kind1 == JavaKind.Byte && kind2 == JavaKind.Byte) {
+            stride2x2 = 0x20;
+        }
+
+        // if (ae == StrIntrinsicNode::LU || ae == StrIntrinsicNode::UL) {
+        if (kind1 != kind2) {
+            masm.shrl(cnt2, 1);
+        }
+        // Compute the minimum of the string lengths and the
+        // difference of the string lengths (stack).
+        // Do the conditional move stuff
+        masm.movl(result, cnt1);
+        masm.subl(cnt1, cnt2);
+        masm.push(cnt1);
+        masm.cmovl(ConditionFlag.LessEqual, cnt2, result);    // cnt2 = min(cnt1, cnt2)
+
+        // Is the minimum length zero?
+        masm.testl(cnt2, cnt2);
+        masm.jcc(ConditionFlag.Zero, LENGTH_DIFF_LABEL);
+        // if (ae == StrIntrinsicNode::LL) {
+        if (kind1 == JavaKind.Byte && kind2 == JavaKind.Byte) {
+            // Load first bytes
+            masm.movzbl(result, new AMD64Address(str1, 0));  // result = str1[0]
+            masm.movzbl(cnt1, new AMD64Address(str2, 0));    // cnt1 = str2[0]
+            // } else if (ae == StrIntrinsicNode::UU) {
+        } else if (kind1 == JavaKind.Char && kind2 == JavaKind.Char) {
+            // Load first characters
+            masm.movzwl(result, new AMD64Address(str1, 0));
+            masm.movzwl(cnt1, new AMD64Address(str2, 0));
+        } else {
+            masm.movzbl(result, new AMD64Address(str1, 0));
+            masm.movzwl(cnt1, new AMD64Address(str2, 0));
+        }
+        masm.subl(result, cnt1);
+        masm.jcc(ConditionFlag.NotZero, POP_LABEL);
+
+        // if (ae == StrIntrinsicNode::UU) {
+        if (kind1 == JavaKind.Char && kind2 == JavaKind.Char) {
+            // Divide length by 2 to get number of chars
+            masm.shrl(cnt2, 1);
+        }
+        masm.cmpl(cnt2, 1);
+        masm.jcc(ConditionFlag.Equal, LENGTH_DIFF_LABEL);
+
+        // Check if the strings start at the same location and setup scale and stride
+        // if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
+        if (kind1 == kind2) {
+            masm.cmpptr(str1, str2);
+            masm.jcc(ConditionFlag.Equal, LENGTH_DIFF_LABEL);
+            // if (ae == StrIntrinsicNode::LL) {
+            if (kind1 == JavaKind.Byte && kind2 == JavaKind.Byte) {
+                scale = AMD64Address.Scale.Times1;
+                stride = 16;
+            } else {
+                scale = AMD64Address.Scale.Times2;
+                stride = 8;
+            }
+        } else {
+            scale1 = AMD64Address.Scale.Times1;
+            scale2 = AMD64Address.Scale.Times2;
+            // scale not used
+            stride = 8;
+        }
+
+        // if (UseAVX >= 2 && UseSSE42Intrinsics) {
+        if (supportsAVX2(crb.target) && supportsSSE42(crb.target)) {
+            Register vec1 = asRegister(vectorTemp1, AMD64Kind.DOUBLE);
+
+            // Checkstyle: stop
+            Label COMPARE_WIDE_VECTORS = new Label();
+            Label VECTOR_NOT_EQUAL = new Label();
+            Label COMPARE_WIDE_TAIL = new Label();
+            Label COMPARE_SMALL_STR = new Label();
+            Label COMPARE_WIDE_VECTORS_LOOP = new Label();
+            Label COMPARE_16_CHARS = new Label();
+            Label COMPARE_INDEX_CHAR = new Label();
+            Label COMPARE_WIDE_VECTORS_LOOP_AVX2 = new Label();
+            Label COMPARE_TAIL_LONG = new Label();
+            Label COMPARE_WIDE_VECTORS_LOOP_AVX3 = new Label();  // used only _LP64 && AVX3
+            // Checkstyle: resume
+
+            int pcmpmask = 0x19;
+            // if (ae == StrIntrinsicNode::LL) {
+            if (kind1 == JavaKind.Byte && kind2 == JavaKind.Byte) {
+                pcmpmask &= ~0x01;
+            }
+
+            // Setup to compare 16-chars (32-bytes) vectors,
+            // start from first character again because it has aligned address.
+            // if (ae == StrIntrinsicNode::LL) {
+            if (kind1 == JavaKind.Byte && kind2 == JavaKind.Byte) {
+                stride2 = 32;
+            } else {
+                stride2 = 16;
+            }
+            // if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
+            if (kind1 == kind2) {
+                adr_stride = stride << scale.log2;
+            } else {
+                adr_stride1 = 8;  // stride << scale1;
+                adr_stride2 = 16; // stride << scale2;
+            }
+
+            assert result.equals(rax) && cnt2.equals(rdx) && cnt1.equals(rcx) : "pcmpestri";
+            // rax and rdx are used by pcmpestri as elements counters
+            masm.movl(result, cnt2);
+            masm.andl(cnt2, ~(stride2 - 1));   // cnt2 holds the vector count
+            masm.jcc(ConditionFlag.Zero, COMPARE_TAIL_LONG);
+
+            // fast path : compare first 2 8-char vectors.
+            masm.bind(COMPARE_16_CHARS);
+            // if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
+            if (kind1 == kind2) {
+                masm.movdqu(vec1, new AMD64Address(str1, 0));
+            } else {
+                masm.pmovzxbw(vec1, new AMD64Address(str1, 0));
+            }
+            masm.pcmpestri(vec1, new AMD64Address(str2, 0), pcmpmask);
+            masm.jccb(ConditionFlag.Below, COMPARE_INDEX_CHAR);
+
+            // if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
+            if (kind1 == kind2) {
+                masm.movdqu(vec1, new AMD64Address(str1, adr_stride));
+                masm.pcmpestri(vec1, new AMD64Address(str2, adr_stride), pcmpmask);
+            } else {
+                masm.pmovzxbw(vec1, new AMD64Address(str1, adr_stride1));
+                masm.pcmpestri(vec1, new AMD64Address(str2, adr_stride2), pcmpmask);
+            }
+            masm.jccb(ConditionFlag.AboveEqual, COMPARE_WIDE_VECTORS);
+            masm.addl(cnt1, stride);
+
+            // Compare the characters at index in cnt1
+            masm.bind(COMPARE_INDEX_CHAR); // cnt1 has the offset of the mismatching character
+            loadNextElements(masm, result, cnt2, str1, str2, scale, scale1, scale2, cnt1);
+            masm.subl(result, cnt2);
+            masm.jmp(POP_LABEL);
+
+            // Setup the registers to start vector comparison loop
+            masm.bind(COMPARE_WIDE_VECTORS);
+            // if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
+            if (kind1 == kind2) {
+                masm.leaq(str1, new AMD64Address(str1, result, scale));
+                masm.leaq(str2, new AMD64Address(str2, result, scale));
+            } else {
+                masm.leaq(str1, new AMD64Address(str1, result, scale1));
+                masm.leaq(str2, new AMD64Address(str2, result, scale2));
+            }
+            masm.subl(result, stride2);
+            masm.subl(cnt2, stride2);
+            masm.jcc(ConditionFlag.Zero, COMPARE_WIDE_TAIL);
+            masm.negq(result);
+
+            // In a loop, compare 16-chars (32-bytes) at once using (vpxor+vptest)
+            masm.bind(COMPARE_WIDE_VECTORS_LOOP);
+
+            // if (VM_Version::supports_avx512vlbw()) { // trying 64 bytes fast loop
+            if (supportsAVX512VLBW(crb.target)) {
+                masm.cmpl(cnt2, stride2x2);
+                masm.jccb(ConditionFlag.Below, COMPARE_WIDE_VECTORS_LOOP_AVX2);
+                masm.testl(cnt2, stride2x2 - 1);   // cnt2 holds the vector count
+                // means we cannot subtract by 0x40
+                masm.jccb(ConditionFlag.NotZero, COMPARE_WIDE_VECTORS_LOOP_AVX2);
+
+                masm.bind(COMPARE_WIDE_VECTORS_LOOP_AVX3); // the hottest loop
+                // if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
+                if (kind1 == kind2) {
+                    masm.evmovdquq(vec1, new AMD64Address(str1, result, scale), AvxVectorLen.AVX_512bit);
+                    // k7 == 11..11, if operands equal, otherwise k7 has some 0
+                    masm.evpcmpeqb(k7, vec1, new AMD64Address(str2, result, scale), AvxVectorLen.AVX_512bit);
+                } else {
+                    masm.vpmovzxbw(vec1, new AMD64Address(str1, result, scale1), AvxVectorLen.AVX_512bit);
+                    // k7 == 11..11, if operands equal, otherwise k7 has some 0
+                    masm.evpcmpeqb(k7, vec1, new AMD64Address(str2, result, scale2), AvxVectorLen.AVX_512bit);
+                }
+                masm.kortestql(k7, k7);
+                masm.jcc(ConditionFlag.AboveEqual, COMPARE_WIDE_VECTORS_LOOP_FAILED);     // miscompare
+                masm.addq(result, stride2x2);  // update since we already compared at this addr
+                masm.subl(cnt2, stride2x2);      // and sub the size too
+                masm.jccb(ConditionFlag.NotZero, COMPARE_WIDE_VECTORS_LOOP_AVX3);
+
+                masm.vpxor(vec1, vec1, vec1);
+                masm.jmpb(COMPARE_WIDE_TAIL);
+            }
+
+            masm.bind(COMPARE_WIDE_VECTORS_LOOP_AVX2);
+            // if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
+            if (kind1 == kind2) {
+                masm.vmovdqu(vec1, new AMD64Address(str1, result, scale));
+                masm.vpxor(vec1, vec1, new AMD64Address(str2, result, scale));
+            } else {
+                masm.vpmovzxbw(vec1, new AMD64Address(str1, result, scale1), AvxVectorLen.AVX_256bit);
+                masm.vpxor(vec1, vec1, new AMD64Address(str2, result, scale2));
+            }
+            masm.vptest(vec1, vec1);
+            masm.jcc(ConditionFlag.NotZero, VECTOR_NOT_EQUAL);
+            masm.addq(result, stride2);
+            masm.subl(cnt2, stride2);
+            masm.jcc(ConditionFlag.NotZero, COMPARE_WIDE_VECTORS_LOOP);
+            // clean upper bits of YMM registers
+            masm.vpxor(vec1, vec1, vec1);
+
+            // compare wide vectors tail
+            masm.bind(COMPARE_WIDE_TAIL);
+            masm.testq(result, result);
+            masm.jcc(ConditionFlag.Zero, LENGTH_DIFF_LABEL);
+
+            masm.movl(result, stride2);
+            masm.movl(cnt2, result);
+            masm.negq(result);
+            masm.jmp(COMPARE_WIDE_VECTORS_LOOP_AVX2);
+
+            // Identifies the mismatching (higher or lower)16-bytes in the 32-byte vectors.
+            masm.bind(VECTOR_NOT_EQUAL);
+            // clean upper bits of YMM registers
+            masm.vpxor(vec1, vec1, vec1);
+            // if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
+            if (kind1 == kind2) {
+                masm.leaq(str1, new AMD64Address(str1, result, scale));
+                masm.leaq(str2, new AMD64Address(str2, result, scale));
+            } else {
+                masm.leaq(str1, new AMD64Address(str1, result, scale1));
+                masm.leaq(str2, new AMD64Address(str2, result, scale2));
+            }
+            masm.jmp(COMPARE_16_CHARS);
+
+            // Compare tail chars, length between 1 to 15 chars
+            masm.bind(COMPARE_TAIL_LONG);
+            masm.movl(cnt2, result);
+            masm.cmpl(cnt2, stride);
+            masm.jcc(ConditionFlag.Less, COMPARE_SMALL_STR);
+
+            // if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
+            if (kind1 == kind2) {
+                masm.movdqu(vec1, new AMD64Address(str1, 0));
+            } else {
+                masm.pmovzxbw(vec1, new AMD64Address(str1, 0));
+            }
+            masm.pcmpestri(vec1, new AMD64Address(str2, 0), pcmpmask);
+            masm.jcc(ConditionFlag.Below, COMPARE_INDEX_CHAR);
+            masm.subq(cnt2, stride);
+            masm.jcc(ConditionFlag.Zero, LENGTH_DIFF_LABEL);
+            // if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
+            if (kind1 == kind2) {
+                masm.leaq(str1, new AMD64Address(str1, result, scale));
+                masm.leaq(str2, new AMD64Address(str2, result, scale));
+            } else {
+                masm.leaq(str1, new AMD64Address(str1, result, scale1));
+                masm.leaq(str2, new AMD64Address(str2, result, scale2));
+            }
+            masm.negq(cnt2);
+            masm.jmpb(WHILE_HEAD_LABEL);
+
+            masm.bind(COMPARE_SMALL_STR);
+        } else if (supportsSSE42(crb.target)) {
+            Register vec1 = asRegister(vectorTemp1, AMD64Kind.DOUBLE);
+
+            // Checkstyle: stop
+            Label COMPARE_WIDE_VECTORS = new Label();
+            Label VECTOR_NOT_EQUAL = new Label();
+            Label COMPARE_TAIL = new Label();
+            // Checkstyle: resume
+            int pcmpmask = 0x19;
+            // Setup to compare 8-char (16-byte) vectors,
+            // start from first character again because it has aligned address.
+            masm.movl(result, cnt2);
+            masm.andl(cnt2, ~(stride - 1));   // cnt2 holds the vector count
+            // if (ae == StrIntrinsicNode::LL) {
+            if (kind1 == JavaKind.Byte && kind2 == JavaKind.Byte) {
+                pcmpmask &= ~0x01;
+            }
+            masm.jcc(ConditionFlag.Zero, COMPARE_TAIL);
+            // if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
+            if (kind1 == kind2) {
+                masm.leaq(str1, new AMD64Address(str1, result, scale));
+                masm.leaq(str2, new AMD64Address(str2, result, scale));
+            } else {
+                masm.leaq(str1, new AMD64Address(str1, result, scale1));
+                masm.leaq(str2, new AMD64Address(str2, result, scale2));
+            }
+            masm.negq(result);
+
+            // pcmpestri
+            // inputs:
+            // vec1- substring
+            // rax - negative string length (elements count)
+            // mem - scanned string
+            // rdx - string length (elements count)
+            // pcmpmask - cmp mode: 11000 (string compare with negated result)
+            // + 00 (unsigned bytes) or + 01 (unsigned shorts)
+            // outputs:
+            // rcx - first mismatched element index
+            assert result.equals(rax) && cnt2.equals(rdx) && cnt1.equals(rcx) : "pcmpestri";
+
+            masm.bind(COMPARE_WIDE_VECTORS);
+            // if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
+            if (kind1 == kind2) {
+                masm.movdqu(vec1, new AMD64Address(str1, result, scale));
+                masm.pcmpestri(vec1, new AMD64Address(str2, result, scale), pcmpmask);
+            } else {
+                masm.pmovzxbw(vec1, new AMD64Address(str1, result, scale1));
+                masm.pcmpestri(vec1, new AMD64Address(str2, result, scale2), pcmpmask);
+            }
+            // After pcmpestri cnt1(rcx) contains mismatched element index
+
+            masm.jccb(ConditionFlag.Below, VECTOR_NOT_EQUAL);  // CF==1
+            masm.addq(result, stride);
+            masm.subq(cnt2, stride);
+            masm.jccb(ConditionFlag.NotZero, COMPARE_WIDE_VECTORS);
+
+            // compare wide vectors tail
+            masm.testq(result, result);
+            masm.jcc(ConditionFlag.Zero, LENGTH_DIFF_LABEL);
+
+            masm.movl(cnt2, stride);
+            masm.movl(result, stride);
+            masm.negq(result);
+            // if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
+            if (kind1 == kind2) {
+                masm.movdqu(vec1, new AMD64Address(str1, result, scale));
+                masm.pcmpestri(vec1, new AMD64Address(str2, result, scale), pcmpmask);
+            } else {
+                masm.pmovzxbw(vec1, new AMD64Address(str1, result, scale1));
+                masm.pcmpestri(vec1, new AMD64Address(str2, result, scale2), pcmpmask);
+            }
+            masm.jccb(ConditionFlag.AboveEqual, LENGTH_DIFF_LABEL);
+
+            // Mismatched characters in the vectors
+            masm.bind(VECTOR_NOT_EQUAL);
+            masm.addq(cnt1, result);
+            loadNextElements(masm, result, cnt2, str1, str2, scale, scale1, scale2, cnt1);
+            masm.subl(result, cnt2);
+            masm.jmpb(POP_LABEL);
+
+            masm.bind(COMPARE_TAIL); // limit is zero
+            masm.movl(cnt2, result);
+            // Fallthru to tail compare
+        }
+
+        // Shift str2 and str1 to the end of the arrays, negate min
+        // if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
+        if (kind1 == kind2) {
+            masm.leaq(str1, new AMD64Address(str1, cnt2, scale));
+            masm.leaq(str2, new AMD64Address(str2, cnt2, scale));
+        } else {
+            masm.leaq(str1, new AMD64Address(str1, cnt2, scale1));
+            masm.leaq(str2, new AMD64Address(str2, cnt2, scale2));
+        }
+        masm.decrementl(cnt2);  // first character was compared already
+        masm.negq(cnt2);
+
+        // Compare the rest of the elements
+        masm.bind(WHILE_HEAD_LABEL);
+        loadNextElements(masm, result, cnt1, str1, str2, scale, scale1, scale2, cnt2);
+        masm.subl(result, cnt1);
+        masm.jccb(ConditionFlag.NotZero, POP_LABEL);
+        masm.incrementq(cnt2, 1);
+        masm.jccb(ConditionFlag.NotZero, WHILE_HEAD_LABEL);
+
+        // Strings are equal up to min length. Return the length difference.
+        masm.bind(LENGTH_DIFF_LABEL);
+        masm.pop(result);
+        // if (ae == StrIntrinsicNode::UU) {
+        if (kind1 == JavaKind.Char && kind2 == JavaKind.Char) {
+            // Divide diff by 2 to get number of chars
+            masm.sarl(result, 1);
+        }
+        masm.jmpb(DONE_LABEL);
+
+        // if (VM_Version::supports_avx512vlbw()) {
+        if (supportsAVX512VLBW(crb.target)) {
+            masm.bind(COMPARE_WIDE_VECTORS_LOOP_FAILED);
+
+            masm.kmovql(cnt1, k7);
+            masm.notq(cnt1);
+            masm.bsfq(cnt2, cnt1);
+            // if (ae != StrIntrinsicNode::LL) {
+            if (kind1 != JavaKind.Byte && kind2 != JavaKind.Byte) {
+                // Divide diff by 2 to get number of chars
+                masm.sarl(cnt2, 1);
+            }
+            masm.addq(result, cnt2);
+            // if (ae == StrIntrinsicNode::LL) {
+            if (kind1 == JavaKind.Byte && kind2 == JavaKind.Byte) {
+                masm.movzbl(cnt1, new AMD64Address(str2, result, Scale.Times1));
+                masm.movzbl(result, new AMD64Address(str1, result, Scale.Times1));
+            } else if (kind1 == JavaKind.Char && kind2 == JavaKind.Char) {
+                masm.movzwl(cnt1, new AMD64Address(str2, result, scale));
+                masm.movzwl(result, new AMD64Address(str1, result, scale));
+            } else {
+                masm.movzwl(cnt1, new AMD64Address(str2, result, scale2));
+                masm.movzbl(result, new AMD64Address(str1, result, scale1));
+            }
+            masm.subl(result, cnt1);
+            masm.jmpb(POP_LABEL);
+        }
+
+        // Discard the stored length difference
+        masm.bind(POP_LABEL);
+        masm.pop(cnt1);
+
+        // That's it
+        masm.bind(DONE_LABEL);
+        // if (ae == StrIntrinsicNode::UL) {
+        if (kind1 == JavaKind.Char && kind2 == JavaKind.Byte) {
+            masm.negl(result);
+        }
+    }
+
+    private void loadNextElements(AMD64MacroAssembler masm, Register elem1, Register elem2, Register str1, Register str2,
+                    AMD64Address.Scale scale, AMD64Address.Scale scale1,
+                    AMD64Address.Scale scale2, Register index) {
+        // if (ae == StrIntrinsicNode::LL) {
+        if (kind1 == JavaKind.Byte && kind2 == JavaKind.Byte) {
+            masm.movzbl(elem1, new AMD64Address(str1, index, scale, 0));
+            masm.movzbl(elem2, new AMD64Address(str2, index, scale, 0));
+            // } else if (ae == StrIntrinsicNode::UU) {
+        } else if (kind1 == JavaKind.Char && kind2 == JavaKind.Char) {
+            masm.movzwl(elem1, new AMD64Address(str1, index, scale, 0));
+            masm.movzwl(elem2, new AMD64Address(str2, index, scale, 0));
+        } else {
+            masm.movzbl(elem1, new AMD64Address(str1, index, scale1, 0));
+            masm.movzwl(elem2, new AMD64Address(str2, index, scale2, 0));
+        }
+    }
+
+    private static final Unsafe UNSAFE = initUnsafe();
+
+    private static Unsafe initUnsafe() {
+        try {
+            return Unsafe.getUnsafe();
+        } catch (SecurityException se) {
+            try {
+                Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
+                theUnsafe.setAccessible(true);
+                return (Unsafe) theUnsafe.get(Unsafe.class);
+            } catch (Exception e) {
+                throw new RuntimeException("exception while trying to get Unsafe", e);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64LFenceOp.java	Fri Mar 16 22:59:32 2018 -0700
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2018, 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.lir.amd64;
+
+import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
+import org.graalvm.compiler.lir.LIRInstructionClass;
+import org.graalvm.compiler.lir.Opcode;
+import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
+
+@Opcode("LFENCE")
+public final class AMD64LFenceOp extends AMD64LIRInstruction {
+    public static final LIRInstructionClass<AMD64LFenceOp> TYPE = LIRInstructionClass.create(AMD64LFenceOp.class);
+
+    public AMD64LFenceOp() {
+        super(TYPE);
+    }
+
+    @Override
+    public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler asm) {
+        asm.lfence();
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java	Fri Mar 16 22:59:32 2018 -0700
@@ -22,6 +22,11 @@
  */
 package org.graalvm.compiler.lir.amd64;
 
+import static java.lang.Double.doubleToRawLongBits;
+import static java.lang.Float.floatToRawIntBits;
+import static jdk.vm.ci.code.ValueUtil.asRegister;
+import static jdk.vm.ci.code.ValueUtil.isRegister;
+import static jdk.vm.ci.code.ValueUtil.isStackSlot;
 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag.Equal;
 import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.COMPOSITE;
@@ -33,21 +38,16 @@
 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.UNINITIALIZED;
 import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant;
 import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant;
-import static java.lang.Double.doubleToRawLongBits;
-import static java.lang.Float.floatToRawIntBits;
-import static jdk.vm.ci.code.ValueUtil.asRegister;
-import static jdk.vm.ci.code.ValueUtil.isRegister;
-import static jdk.vm.ci.code.ValueUtil.isStackSlot;
 
 import org.graalvm.compiler.asm.Label;
-import org.graalvm.compiler.core.common.CompressEncoding;
-import org.graalvm.compiler.core.common.LIRKind;
-import org.graalvm.compiler.core.common.NumUtil;
 import org.graalvm.compiler.asm.amd64.AMD64Address;
 import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp;
 import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MOp;
 import org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize;
 import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
+import org.graalvm.compiler.core.common.CompressEncoding;
+import org.graalvm.compiler.core.common.LIRKind;
+import org.graalvm.compiler.core.common.NumUtil;
 import org.graalvm.compiler.core.common.spi.LIRKindTool;
 import org.graalvm.compiler.core.common.type.DataPointerConstant;
 import org.graalvm.compiler.debug.GraalError;
@@ -59,6 +59,7 @@
 import org.graalvm.compiler.lir.StandardOp.ValueMoveOp;
 import org.graalvm.compiler.lir.VirtualStackSlot;
 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
+import org.graalvm.compiler.options.OptionValues;
 
 import jdk.vm.ci.amd64.AMD64;
 import jdk.vm.ci.amd64.AMD64Kind;
@@ -763,7 +764,7 @@
 
         @Def({REG, HINT}) private AllocatableValue result;
         @Use({REG, CONST}) private Value input;
-        @Alive({REG, ILLEGAL}) private AllocatableValue baseRegister;
+        @Alive({REG, ILLEGAL, UNINITIALIZED}) private AllocatableValue baseRegister;
 
         protected PointerCompressionOp(LIRInstructionClass<? extends PointerCompressionOp> type, AllocatableValue result, Value input,
                         AllocatableValue baseRegister, CompressEncoding encoding, boolean nonNull, LIRKindTool lirKindTool) {
@@ -777,8 +778,8 @@
             this.lirKindTool = lirKindTool;
         }
 
-        protected boolean hasBase(CompilationResultBuilder crb) {
-            return GeneratePIC.getValue(crb.getOptions()) || encoding.hasBase();
+        public static boolean hasBase(OptionValues options, CompressEncoding encoding) {
+            return GeneratePIC.getValue(options) || encoding.hasBase();
         }
 
         public final Value getInput() {
@@ -820,7 +821,7 @@
             move(lirKindTool.getObjectKind(), crb, masm);
 
             Register resReg = asRegister(getResult());
-            if (hasBase(crb)) {
+            if (hasBase(crb.getOptions(), encoding)) {
                 Register baseReg = getBaseRegister();
                 if (!nonNull) {
                     masm.testq(resReg, resReg);
@@ -852,15 +853,15 @@
         @Override
         public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
             move(lirKindTool.getNarrowOopKind(), crb, masm);
+            emitUncompressCode(masm, asRegister(getResult()), getShift(), hasBase(crb.getOptions(), encoding) ? getBaseRegister() : null, nonNull);
+        }
 
-            Register resReg = asRegister(getResult());
-            int shift = getShift();
+        public static void emitUncompressCode(AMD64MacroAssembler masm, Register resReg, int shift, Register baseReg, boolean nonNull) {
             if (shift != 0) {
                 masm.shlq(resReg, shift);
             }
 
-            if (hasBase(crb)) {
-                Register baseReg = getBaseRegister();
+            if (baseReg != null) {
                 if (nonNull) {
                     masm.addq(resReg, baseReg);
                     return;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRInstructionClass.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRInstructionClass.java	Fri Mar 16 22:59:32 2018 -0700
@@ -96,7 +96,11 @@
         try {
             Field field = clazz.getDeclaredField("TYPE");
             field.setAccessible(true);
-            return (LIRInstructionClass<T>) field.get(null);
+            LIRInstructionClass<T> result = (LIRInstructionClass<T>) field.get(null);
+            if (result == null) {
+                throw GraalError.shouldNotReachHere("TYPE field not initialized for class " + clazz.getTypeName());
+            }
+            return result;
         } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) {
             throw new RuntimeException(e);
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/GlobalLivenessInfo.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/GlobalLivenessInfo.java	Fri Mar 16 22:59:32 2018 -0700
@@ -53,7 +53,11 @@
         public final int[] emptySet;
 
         public Builder(LIR lir) {
-            info = new GlobalLivenessInfo(lir);
+            this(lir.numVariables(), lir.getControlFlowGraph().getBlocks().length);
+        }
+
+        public Builder(int numVariables, int numBlocks) {
+            info = new GlobalLivenessInfo(numVariables, numBlocks);
             emptySet = new int[0];
         }
 
@@ -97,10 +101,8 @@
     private final Value[][] blockToLocIn;
     private final Value[][] blockToLocOut;
 
-    private GlobalLivenessInfo(LIR lir) {
-        int numVariables = lir.numVariables();
+    private GlobalLivenessInfo(int numVariables, int numBlocks) {
         variables = new Variable[numVariables];
-        int numBlocks = lir.getControlFlowGraph().getBlocks().length;
         blockToVarIn = new int[numBlocks][];
         blockToVarOut = new int[numBlocks][];
         blockToLocIn = new Value[numBlocks][];
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TraceAssertions.java	Fri Mar 16 22:59:32 2018 -0700
@@ -0,0 +1,69 @@
+/*
+ * 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.lir.alloc.trace;
+
+import org.graalvm.compiler.core.common.alloc.Trace;
+import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
+
+/**
+ * A collection of assertions that are assumed to hold in various places of the Trace Register
+ * Allocation framework.
+ *
+ * The main goal is to document pieces of code that rely on specific properties of traces. In case
+ * an assumption is no longer valid, this makes it easy (assumed they are used correctly) to find
+ * places that need changes.
+ */
+final class TraceAssertions {
+
+    /**
+     * Asserts that variable indices are properly sorted.
+     */
+    public static boolean liveSetsAreSorted(GlobalLivenessInfo livenessInfo, AbstractBlockBase<?> block) {
+        return isSorted(livenessInfo.getBlockIn(block)) && isSorted(livenessInfo.getBlockOut(block));
+    }
+
+    private static boolean isSorted(int[] live) {
+        if (live.length == 0) {
+            return true;
+        }
+        int current = live[0];
+        for (int i = 1; i < live.length; i++) {
+            int last = current;
+            current = live[i];
+            if (current <= last) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Asserts that a trace head has only a single predecessor.
+     *
+     * This is not true for every trace-building algorithm (for example
+     * {@link TraceBuilderPhase.TraceBuilder#SingleBlock}).
+     */
+    public static boolean singleHeadPredecessor(Trace trace) {
+        return trace.getBlocks()[0].getPredecessorCount() == 1;
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TraceGlobalMoveResolutionPhase.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TraceGlobalMoveResolutionPhase.java	Fri Mar 16 22:59:32 2018 -0700
@@ -84,32 +84,58 @@
         DebugContext debug = lir.getDebug();
         try (Indent indent = debug.logAndIndent("Trace global move resolution")) {
             for (Trace trace : resultTraces.getTraces()) {
-                for (AbstractBlockBase<?> fromBlock : trace.getBlocks()) {
-                    for (AbstractBlockBase<?> toBlock : fromBlock.getSuccessors()) {
-                        if (resultTraces.getTraceForBlock(fromBlock) != resultTraces.getTraceForBlock(toBlock)) {
-                            try (Indent indent0 = debug.logAndIndent("Handle trace edge from %s (Trace%d) to %s (Trace%d)", fromBlock, resultTraces.getTraceForBlock(fromBlock).getId(), toBlock,
-                                            resultTraces.getTraceForBlock(toBlock).getId())) {
+                resolveTrace(resultTraces, livenessInfo, lir, moveResolver, trace);
+            }
+        }
+    }
 
-                                final ArrayList<LIRInstruction> instructions;
-                                final int insertIdx;
-                                if (fromBlock.getSuccessorCount() == 1) {
-                                    instructions = lir.getLIRforBlock(fromBlock);
-                                    insertIdx = instructions.size() - 1;
-                                } else {
-                                    assert toBlock.getPredecessorCount() == 1;
-                                    instructions = lir.getLIRforBlock(toBlock);
-                                    insertIdx = 1;
-                                }
-
-                                moveResolver.setInsertPosition(instructions, insertIdx);
-                                resolveEdge(lir, livenessInfo, moveResolver, fromBlock, toBlock);
-                                moveResolver.resolveAndAppendMoves();
-                            }
-                        }
+    private static void resolveTrace(TraceBuilderResult resultTraces, GlobalLivenessInfo livenessInfo, LIR lir, TraceGlobalMoveResolver moveResolver, Trace trace) {
+        AbstractBlockBase<?>[] traceBlocks = trace.getBlocks();
+        int traceLength = traceBlocks.length;
+        // all but the last block
+        AbstractBlockBase<?> nextBlock = traceBlocks[0];
+        for (int i = 1; i < traceLength; i++) {
+            AbstractBlockBase<?> fromBlock = nextBlock;
+            nextBlock = traceBlocks[i];
+            if (fromBlock.getSuccessorCount() > 1) {
+                for (AbstractBlockBase<?> toBlock : fromBlock.getSuccessors()) {
+                    if (toBlock != nextBlock) {
+                        interTraceEdge(resultTraces, livenessInfo, lir, moveResolver, fromBlock, toBlock);
                     }
                 }
             }
         }
+        // last block
+        assert nextBlock == traceBlocks[traceLength - 1];
+        for (AbstractBlockBase<?> toBlock : nextBlock.getSuccessors()) {
+            if (resultTraces.getTraceForBlock(nextBlock) != resultTraces.getTraceForBlock(toBlock)) {
+                interTraceEdge(resultTraces, livenessInfo, lir, moveResolver, nextBlock, toBlock);
+            }
+        }
+    }
+
+    @SuppressWarnings("try")
+    private static void interTraceEdge(TraceBuilderResult resultTraces, GlobalLivenessInfo livenessInfo, LIR lir, TraceGlobalMoveResolver moveResolver, AbstractBlockBase<?> fromBlock,
+                    AbstractBlockBase<?> toBlock) {
+        DebugContext debug = lir.getDebug();
+        try (Indent indent0 = debug.logAndIndent("Handle trace edge from %s (Trace%d) to %s (Trace%d)", fromBlock, resultTraces.getTraceForBlock(fromBlock).getId(), toBlock,
+                        resultTraces.getTraceForBlock(toBlock).getId())) {
+
+            final ArrayList<LIRInstruction> instructions;
+            final int insertIdx;
+            if (fromBlock.getSuccessorCount() == 1) {
+                instructions = lir.getLIRforBlock(fromBlock);
+                insertIdx = instructions.size() - 1;
+            } else {
+                assert toBlock.getPredecessorCount() == 1;
+                instructions = lir.getLIRforBlock(toBlock);
+                insertIdx = 1;
+            }
+
+            moveResolver.setInsertPosition(instructions, insertIdx);
+            resolveEdge(lir, livenessInfo, moveResolver, fromBlock, toBlock);
+            moveResolver.resolveAndAppendMoves();
+        }
     }
 
     private static void resolveEdge(LIR lir, GlobalLivenessInfo livenessInfo, TraceGlobalMoveResolver moveResolver, AbstractBlockBase<?> fromBlock, AbstractBlockBase<?> toBlock) {
@@ -129,6 +155,10 @@
         // GLI
         Value[] locFrom = livenessInfo.getOutLocation(fromBlock);
         Value[] locTo = livenessInfo.getInLocation(toBlock);
+        if (locFrom == locTo) {
+            // a strategy might reuse the locations array if locations are the same
+            return;
+        }
         assert locFrom.length == locTo.length;
 
         for (int i = 0; i < locFrom.length; i++) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TraceUtil.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TraceUtil.java	Fri Mar 16 22:59:32 2018 -0700
@@ -36,19 +36,6 @@
 
 public class TraceUtil {
 
-    public static AbstractBlockBase<?> getBestTraceInterPredecessor(TraceBuilderResult traceResult, AbstractBlockBase<?> block) {
-        AbstractBlockBase<?> bestPred = null;
-        int bestTraceId = traceResult.getTraceForBlock(block).getId();
-        for (AbstractBlockBase<?> pred : block.getPredecessors()) {
-            int predTraceId = traceResult.getTraceForBlock(pred).getId();
-            if (predTraceId < bestTraceId) {
-                bestPred = pred;
-                bestTraceId = predTraceId;
-            }
-        }
-        return bestPred;
-    }
-
     public static boolean isShadowedRegisterValue(Value value) {
         assert value != null;
         return value instanceof ShadowedRegisterValue;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TrivialTraceAllocator.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TrivialTraceAllocator.java	Fri Mar 16 22:59:32 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -26,12 +26,13 @@
 import static org.graalvm.compiler.lir.LIRValueUtil.isVariable;
 import static org.graalvm.compiler.lir.alloc.trace.TraceUtil.isTrivialTrace;
 
+import java.util.Arrays;
 import java.util.EnumSet;
 
 import org.graalvm.compiler.core.common.alloc.Trace;
-import org.graalvm.compiler.core.common.alloc.TraceBuilderResult;
 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
 import org.graalvm.compiler.lir.LIR;
+import org.graalvm.compiler.lir.LIRInstruction;
 import org.graalvm.compiler.lir.LIRInstruction.OperandFlag;
 import org.graalvm.compiler.lir.LIRInstruction.OperandMode;
 import org.graalvm.compiler.lir.StandardOp.JumpOp;
@@ -47,68 +48,67 @@
  * Allocates a trivial trace i.e. a trace consisting of a single block with no instructions other
  * than the {@link LabelOp} and the {@link JumpOp}.
  */
-final class TrivialTraceAllocator extends TraceAllocationPhase<TraceAllocationPhase.TraceAllocationContext> {
+public final class TrivialTraceAllocator extends TraceAllocationPhase<TraceAllocationPhase.TraceAllocationContext> {
 
     @Override
     protected void run(TargetDescription target, LIRGenerationResult lirGenRes, Trace trace, TraceAllocationContext context) {
         LIR lir = lirGenRes.getLIR();
-        TraceBuilderResult resultTraces = context.resultTraces;
         assert isTrivialTrace(lir, trace) : "Not a trivial trace! " + trace;
         AbstractBlockBase<?> block = trace.getBlocks()[0];
+        assert TraceAssertions.singleHeadPredecessor(trace) : "Trace head with more than one predecessor?!" + trace;
+        AbstractBlockBase<?> pred = block.getPredecessors()[0];
 
-        AbstractBlockBase<?> pred = TraceUtil.getBestTraceInterPredecessor(resultTraces, block);
-
-        Value[] variableMap = new Value[lir.numVariables()];
         GlobalLivenessInfo livenessInfo = context.livenessInfo;
-        collectMapping(block, pred, livenessInfo, variableMap);
-        assignLocations(lir, block, livenessInfo, variableMap);
+        allocate(block, pred, livenessInfo, SSAUtil.phiOutOrNull(lir, block));
     }
 
-    /**
-     * Collects the mapping from variable to location. Additionally the
-     * {@link GlobalLivenessInfo#setInLocations incoming location array} is set.
-     */
-    private static void collectMapping(AbstractBlockBase<?> block, AbstractBlockBase<?> pred, GlobalLivenessInfo livenessInfo, Value[] variableMap) {
+    public static void allocate(AbstractBlockBase<?> block, AbstractBlockBase<?> pred, GlobalLivenessInfo livenessInfo, LIRInstruction jump) {
+        // exploit that the live sets are sorted
+        assert TraceAssertions.liveSetsAreSorted(livenessInfo, block);
+        assert TraceAssertions.liveSetsAreSorted(livenessInfo, pred);
+
+        // setup incoming variables/locations
         final int[] blockIn = livenessInfo.getBlockIn(block);
         final Value[] predLocOut = livenessInfo.getOutLocation(pred);
-        final Value[] locationIn = new Value[blockIn.length];
-        for (int i = 0; i < blockIn.length; i++) {
-            int varNum = blockIn[i];
-            if (varNum >= 0) {
-                Value location = predLocOut[i];
-                variableMap[varNum] = location;
-                locationIn[i] = location;
-            } else {
-                locationIn[i] = Value.ILLEGAL;
+        int inLenght = blockIn.length;
+
+        // setup outgoing variables/locations
+        final int[] blockOut = livenessInfo.getBlockOut(block);
+        int outLength = blockOut.length;
+        final Value[] locationOut = new Value[outLength];
+
+        assert outLength <= inLenght : "Trivial Trace! There cannot be more outgoing values than incoming.";
+        for (int outIdx = 0, inIdx = 0; outIdx < outLength; inIdx++) {
+            if (blockOut[outIdx] == blockIn[inIdx]) {
+                // set the outgoing location to the incoming value
+                locationOut[outIdx++] = predLocOut[inIdx];
             }
         }
-        livenessInfo.setInLocations(block, locationIn);
+
+        /*
+         * Since we do not change any of the location we can just use the outgoing of the
+         * predecessor.
+         */
+        livenessInfo.setInLocations(block, predLocOut);
+        livenessInfo.setOutLocations(block, locationOut);
+        if (jump != null) {
+            handlePhiOut(jump, blockIn, predLocOut);
+        }
     }
 
-    /**
-     * Assigns the outgoing locations according to the {@link #collectMapping variable mapping}.
-     */
-    private static void assignLocations(LIR lir, AbstractBlockBase<?> block, GlobalLivenessInfo livenessInfo, Value[] variableMap) {
-        final int[] blockOut = livenessInfo.getBlockOut(block);
-        final Value[] locationOut = new Value[blockOut.length];
-        for (int i = 0; i < blockOut.length; i++) {
-            int varNum = blockOut[i];
-            locationOut[i] = variableMap[varNum];
-        }
-        livenessInfo.setOutLocations(block, locationOut);
-
+    private static void handlePhiOut(LIRInstruction jump, int[] varIn, Value[] locIn) {
         // handle outgoing phi values
         ValueProcedure outputConsumer = new ValueProcedure() {
             @Override
             public Value doValue(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
                 if (isVariable(value)) {
-                    return variableMap[asVariable(value).index];
+                    // since incoming variables are sorted, we can do a binary search
+                    return locIn[Arrays.binarySearch(varIn, asVariable(value).index)];
                 }
                 return value;
             }
         };
 
-        JumpOp jump = SSAUtil.phiOut(lir, block);
         // Jumps have only alive values (outgoing phi values)
         jump.forEachAlive(outputConsumer);
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/bu/BottomUpAllocator.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/bu/BottomUpAllocator.java	Fri Mar 16 22:59:32 2018 -0700
@@ -501,11 +501,12 @@
 
             try (Indent indent = debug.logAndIndent("handle block %s", block)) {
                 currentInstructions = getLIR().getLIRforBlock(block);
-                for (currentInstructionIndex = currentInstructions.size() - 1; currentInstructionIndex >= 0; currentInstructionIndex--) {
+                final int lastInstIdx = currentInstructions.size() - 1;
+                for (currentInstructionIndex = lastInstIdx; currentInstructionIndex >= 0; currentInstructionIndex--) {
                     LIRInstruction inst = currentInstructions.get(currentInstructionIndex);
                     if (inst != null) {
                         inst.setId(currentOpId);
-                        allocateInstruction(inst, block);
+                        allocateInstruction(inst, block, currentInstructionIndex == 0, currentInstructionIndex == lastInstIdx);
                     }
                 }
                 allocatedBlocks.set(block.getId());
@@ -514,7 +515,7 @@
         }
 
         @SuppressWarnings("try")
-        private void allocateInstruction(LIRInstruction op, AbstractBlockBase<?> block) {
+        private void allocateInstruction(LIRInstruction op, AbstractBlockBase<?> block, boolean isLabel, boolean isBlockEnd) {
             assert op != null && op.id() == currentOpId;
             try (Indent indent = debug.logAndIndent("handle inst: %d: %s", op.id(), op)) {
                 try (Indent indent1 = debug.logAndIndent("output pos")) {
@@ -537,7 +538,8 @@
                     // should have
                     op.forEachTemp(allocStackOrRegisterProcedure);
                     op.forEachOutput(allocStackOrRegisterProcedure);
-                    if (op instanceof LabelOp) {
+                    if (isLabel) {
+                        assert op instanceof LabelOp;
                         processIncoming(block, op);
                     }
                 }
@@ -551,7 +553,8 @@
                     op.forEachInput(allocRegisterProcedure);
 
                     op.forEachAlive(allocStackOrRegisterProcedure);
-                    if (op instanceof BlockEndOp) {
+                    if (isBlockEnd) {
+                        assert op instanceof BlockEndOp;
                         processOutgoing(block, op);
                     }
                     op.forEachState(allocStackOrRegisterProcedure);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLinearScanLifetimeAnalysisPhase.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLinearScanLifetimeAnalysisPhase.java	Fri Mar 16 22:59:32 2018 -0700
@@ -112,10 +112,6 @@
             buildIntervals();
         }
 
-        private boolean isAllocated(AbstractBlockBase<?> currentBlock, AbstractBlockBase<?> other) {
-            return traceBuilderResult.getTraceForBlock(other).getId() < traceBuilderResult.getTraceForBlock(currentBlock).getId();
-        }
-
         /**
          * Count instructions in all blocks. The numbering follows the
          * {@linkplain TraceLinearScan#sortedBlocks() register allocation order}.
@@ -621,26 +617,29 @@
             assert allocator.instructionForId(opId) == op : "must match";
         }
 
+        /**
+         * Add register hints for incoming values, i.e., values that are not defined in the trace.
+         *
+         * Due to the dominance property of SSA form, all values live at some point in the trace
+         * that are not defined in the trace are live at the beginning of it.
+         */
         @SuppressWarnings("try")
         private void addInterTraceHints() {
             try (DebugContext.Scope s = debug.scope("InterTraceHints", allocator)) {
+                AbstractBlockBase<?> traceHeadBlock = sortedBlocks()[0];
+                if (traceHeadBlock.getPredecessorCount() == 0) {
+                    return;
+                }
+                assert traceHeadBlock.getPredecessorCount() == 1 : "Trace head with more than one predecessor?!" + traceHeadBlock;
+
+                AbstractBlockBase<?> pred = traceHeadBlock.getPredecessors()[0];
+                assert traceBuilderResult.getTraceForBlock(pred).getId() < traceBuilderResult.getTraceForBlock(traceHeadBlock).getId() : "Not yet allocated? " + pred;
+
                 GlobalLivenessInfo livenessInfo = allocator.getGlobalLivenessInfo();
-                // set hints for phi/incoming intervals
-                for (AbstractBlockBase<?> block : sortedBlocks()) {
-                    LabelOp label = (LabelOp) getLIR().getLIRforBlock(block).get(0);
-                    for (AbstractBlockBase<?> pred : block.getPredecessors()) {
-                        addInterTraceHints(livenessInfo, pred, block, label);
-                    }
-                }
-            } catch (Throwable e) {
-                throw debug.handle(e);
-            }
-        }
+                LabelOp label = (LabelOp) getLIR().getLIRforBlock(traceHeadBlock).get(0);
 
-        private void addInterTraceHints(GlobalLivenessInfo livenessInfo, AbstractBlockBase<?> from, AbstractBlockBase<?> to, LabelOp label) {
-            if (isAllocated(to, from)) {
-                int[] liveVars = livenessInfo.getBlockIn(to);
-                Value[] outLocation = livenessInfo.getOutLocation(from);
+                int[] liveVars = livenessInfo.getBlockIn(traceHeadBlock);
+                Value[] outLocation = livenessInfo.getOutLocation(pred);
 
                 for (int i = 0; i < liveVars.length; i++) {
                     int varNum = liveVars[i];
@@ -652,18 +651,20 @@
                         }
                     }
                 }
+            } catch (Throwable e) {
+                throw debug.handle(e);
             }
         }
 
         private void addInterTraceHint(LabelOp label, int varNum, Value fromValue) {
-            assert isRegister(fromValue) || isVariable(fromValue) || isStackSlotValue(fromValue) || isShadowedRegisterValue(fromValue) : "Wrong fromValue: " + fromValue;
+            assert isRegister(fromValue) || isStackSlotValue(fromValue) || isShadowedRegisterValue(fromValue) : "Wrong fromValue: " + fromValue;
             TraceInterval to = allocator.intervalFor(varNum);
             if (to == null) {
                 // variable not live -> do nothing
                 return;
             }
-            if (isVariableOrRegister(fromValue)) {
-                IntervalHint from = getIntervalHint((AllocatableValue) fromValue);
+            if (isRegister(fromValue)) {
+                IntervalHint from = allocator.getOrCreateFixedInterval(asRegisterValue(fromValue));
                 setHint(label, to, from, debug);
             } else if (isStackSlotValue(fromValue)) {
                 setSpillSlot(label, to, (AllocatableValue) fromValue, debug);
@@ -672,8 +673,6 @@
                 IntervalHint from = getIntervalHint(shadowedRegisterValue.getRegister());
                 setHint(label, to, from, debug);
                 setSpillSlot(label, to, shadowedRegisterValue.getStackSlot(), debug);
-            } else {
-                throw GraalError.shouldNotReachHere();
             }
         }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGeneratorTool.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGeneratorTool.java	Fri Mar 16 22:59:32 2018 -0700
@@ -252,11 +252,16 @@
 
     Variable emitByteSwap(Value operand);
 
+    @SuppressWarnings("unused")
+    default Variable emitArrayCompareTo(JavaKind kind1, JavaKind kind2, Value array1, Value array2, Value length1, Value length2) {
+        throw GraalError.unimplemented("String.compareTo substitution is not implemented on this architecture");
+    }
+
     Variable emitArrayEquals(JavaKind kind, Value array1, Value array2, Value length);
 
     @SuppressWarnings("unused")
     default Variable emitStringIndexOf(Value sourcePointer, Value sourceCount, Value targetPointer, Value targetCount, int constantTargetCount) {
-        throw GraalError.unimplemented();
+        throw GraalError.unimplemented("String.indexOf substitution is not implemented on this architecture");
     }
 
     void emitBlackhole(Value operand);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/phases/LIRPhaseSuite.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/phases/LIRPhaseSuite.java	Fri Mar 16 22:59:32 2018 -0700
@@ -40,6 +40,13 @@
     }
 
     /**
+     * Gets an unmodifiable view on the phases in this suite.
+     */
+    public List<LIRPhase<C>> getPhases() {
+        return Collections.unmodifiableList(phases);
+    }
+
+    /**
      * Add a new phase at the beginning of this suite.
      */
     public final void prependPhase(LIRPhase<C> phase) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ssa/SSAUtil.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ssa/SSAUtil.java	Fri Mar 16 22:59:32 2018 -0700
@@ -112,6 +112,13 @@
         return (JumpOp) op;
     }
 
+    public static JumpOp phiOutOrNull(LIR lir, AbstractBlockBase<?> block) {
+        if (block.getSuccessorCount() != 1) {
+            return null;
+        }
+        return phiOut(lir, block);
+    }
+
     public static int phiOutIndex(LIR lir, AbstractBlockBase<?> block) {
         assert block.getSuccessorCount() == 1;
         ArrayList<LIRInstruction> instructions = lir.getLIRforBlock(block);
@@ -181,4 +188,19 @@
         return -1;
     }
 
+    public static int numPhiOut(LIR lir, AbstractBlockBase<?> block) {
+        if (block.getSuccessorCount() != 1) {
+            // cannot be a phi_out block
+            return 0;
+        }
+        return numPhiIn(lir, block.getSuccessors()[0]);
+    }
+
+    private static int numPhiIn(LIR lir, AbstractBlockBase<?> block) {
+        if (!isMerge(block)) {
+            return 0;
+        }
+        return phiIn(lir, block).getPhiSize();
+    }
+
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/BasicInductionVariable.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/BasicInductionVariable.java	Fri Mar 16 22:59:32 2018 -0700
@@ -28,6 +28,7 @@
 
 import org.graalvm.compiler.core.common.type.IntegerStamp;
 import org.graalvm.compiler.core.common.type.Stamp;
+import org.graalvm.compiler.core.common.util.UnsignedLong;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.nodes.ConstantNode;
 import org.graalvm.compiler.nodes.NodeView;
@@ -159,7 +160,7 @@
     @Override
     public ValueNode exitValueNode() {
         Stamp stamp = phi.stamp(NodeView.DEFAULT);
-        ValueNode maxTripCount = loop.counted().maxTripCountNode(false);
+        ValueNode maxTripCount = loop.counted().maxTripCountNode();
         if (!maxTripCount.stamp(NodeView.DEFAULT).isCompatible(stamp)) {
             maxTripCount = IntegerConvertNode.convert(maxTripCount, stamp, graph(), NodeView.DEFAULT);
         }
@@ -173,7 +174,11 @@
 
     @Override
     public long constantExtremum() {
-        return constantStride() * (loop.counted().constantMaxTripCount() - 1) + constantInit();
+        UnsignedLong tripCount = loop.counted().constantMaxTripCount();
+        if (tripCount.isLessThan(1)) {
+            return constantInit();
+        }
+        return tripCount.minus(1).wrappingTimes(constantStride()).wrappingPlus(constantInit()).asLong();
     }
 
     @Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/CountedLoopInfo.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/CountedLoopInfo.java	Fri Mar 16 22:59:32 2018 -0700
@@ -23,11 +23,12 @@
 package org.graalvm.compiler.loop;
 
 import static org.graalvm.compiler.loop.MathUtil.add;
-import static org.graalvm.compiler.loop.MathUtil.divBefore;
 import static org.graalvm.compiler.loop.MathUtil.sub;
+import static org.graalvm.compiler.loop.MathUtil.unsignedDivBefore;
 
 import org.graalvm.compiler.core.common.type.IntegerStamp;
 import org.graalvm.compiler.core.common.type.Stamp;
+import org.graalvm.compiler.core.common.util.UnsignedLong;
 import org.graalvm.compiler.loop.InductionVariable.Direction;
 import org.graalvm.compiler.nodes.AbstractBeginNode;
 import org.graalvm.compiler.nodes.ConstantNode;
@@ -39,6 +40,7 @@
 import org.graalvm.compiler.nodes.calc.CompareNode;
 import org.graalvm.compiler.nodes.calc.ConditionalNode;
 import org.graalvm.compiler.nodes.calc.IntegerLessThanNode;
+import org.graalvm.compiler.nodes.calc.NegateNode;
 import org.graalvm.compiler.nodes.extended.GuardingNode;
 
 import jdk.vm.ci.code.CodeUtil;
@@ -64,38 +66,58 @@
         this.ifNode = ifNode;
     }
 
+    /**
+     * Returns a node that computes the maximum trip count of this loop. That is the trip count of
+     * this loop assuming it is not exited by an other exit than the {@linkplain #getLimitTest()
+     * count check}.
+     *
+     * This count is exact if {@link #isExactTripCount()} returns true.
+     *
+     * THIS VALUE SHOULD BE TREATED AS UNSIGNED.
+     */
     public ValueNode maxTripCountNode() {
         return maxTripCountNode(false);
     }
 
+    /**
+     * Returns a node that computes the maximum trip count of this loop. That is the trip count of
+     * this loop assuming it is not exited by an other exit than the {@linkplain #getLimitTest()
+     * count check}.
+     *
+     * This count is exact if {@link #isExactTripCount()} returns true.
+     *
+     * THIS VALUE SHOULD BE TREATED AS UNSIGNED.
+     *
+     * @param assumePositive if true the check that the loop is entered at all will be omitted.
+     */
     public ValueNode maxTripCountNode(boolean assumePositive) {
         StructuredGraph graph = iv.valueNode().graph();
         Stamp stamp = iv.valueNode().stamp(NodeView.DEFAULT);
-        ValueNode range = sub(graph, end, iv.initNode());
 
         ValueNode max;
         ValueNode min;
-        ValueNode oneDirection;
+        ValueNode range;
+        ValueNode absStride;
         if (iv.direction() == Direction.Up) {
-            oneDirection = ConstantNode.forIntegerStamp(stamp, 1, graph);
+            absStride = iv.strideNode();
+            range = sub(graph, end, iv.initNode());
             max = end;
             min = iv.initNode();
         } else {
             assert iv.direction() == Direction.Down;
-            oneDirection = ConstantNode.forIntegerStamp(stamp, -1, graph);
+            absStride = graph.maybeAddOrUnique(NegateNode.create(iv.strideNode(), NodeView.DEFAULT));
+            range = sub(graph, iv.initNode(), end);
             max = iv.initNode();
             min = end;
         }
+
+        ConstantNode one = ConstantNode.forIntegerStamp(stamp, 1, graph);
         if (oneOff) {
-            range = add(graph, range, oneDirection);
+            range = add(graph, range, one);
         }
         // round-away-from-zero divison: (range + stride -/+ 1) / stride
-        ValueNode denominator = range;
-        if (!oneDirection.stamp(NodeView.DEFAULT).equals(iv.strideNode().stamp(NodeView.DEFAULT))) {
-            ValueNode subedRanged = sub(graph, range, oneDirection);
-            denominator = add(graph, subedRanged, iv.strideNode());
-        }
-        ValueNode div = divBefore(graph, loop.entryPoint(), denominator, iv.strideNode());
+        ValueNode denominator = add(graph, range, sub(graph, absStride, one));
+        ValueNode div = unsignedDivBefore(graph, loop.entryPoint(), denominator, absStride);
 
         if (assumePositive) {
             return div;
@@ -105,49 +127,44 @@
     }
 
     /**
-     * @return true if the loop has constant bounds and the trip count is representable as a
-     *         positive integer.
+     * @return true if the loop has constant bounds.
      */
     public boolean isConstantMaxTripCount() {
-        /*
-         * It's possible that the iteration range is too large to treat this as constant because it
-         * will overflow.
-         */
-        return (hasConstantBounds() && rawConstantMaxTripCount() >= 0);
+        return end instanceof ConstantNode && iv.isConstantInit() && iv.isConstantStride();
+    }
+
+    public UnsignedLong constantMaxTripCount() {
+        assert isConstantMaxTripCount();
+        return new UnsignedLong(rawConstantMaxTripCount());
     }
 
     /**
-     * @return true if the bounds on the iteration space are all constants.
+     * Compute the raw value of the trip count for this loop. THIS IS AN UNSIGNED VALUE;
      */
-    public boolean hasConstantBounds() {
-        return end instanceof ConstantNode && iv.isConstantInit() && iv.isConstantStride();
-    }
-
-    public long constantMaxTripCount() {
-        assert isConstantMaxTripCount();
-        return rawConstantMaxTripCount();
-    }
-
-    /**
-     * Compute the raw value of the trip count for this loop. Since we don't have unsigned values
-     * this may be outside representable positive values.
-     */
-    protected long rawConstantMaxTripCount() {
+    private long rawConstantMaxTripCount() {
         assert iv.direction() != null;
-        long off = oneOff ? iv.direction() == Direction.Up ? 1 : -1 : 0;
-        long endValue = ((ConstantNode) end).asJavaConstant().asLong();
-        try {
-            // If no overflow occurs then negative values represent a trip count of 0
-            long max = Math.subtractExact(Math.addExact(endValue, off), iv.constantInit()) / iv.constantStride();
-            return Math.max(0, max);
-        } catch (ArithmeticException e) {
-            /*
-             * The computation overflowed to return a negative value. It's possible some
-             * optimization could handle this value as an unsigned and produce the right answer but
-             * we hide this value by default.
-             */
-            return -1;
+        long endValue = end.asJavaConstant().asLong();
+        long initValue = iv.constantInit();
+        long range;
+        long absStride;
+        if (iv.direction() == Direction.Up) {
+            if (endValue < initValue) {
+                return 0;
+            }
+            range = endValue - iv.constantInit();
+            absStride = iv.constantStride();
+        } else {
+            if (initValue < endValue) {
+                return 0;
+            }
+            range = iv.constantInit() - endValue;
+            absStride = -iv.constantStride();
         }
+        if (oneOff) {
+            range += 1;
+        }
+        long denominator = range + absStride - 1;
+        return Long.divideUnsigned(denominator, absStride);
     }
 
     public boolean isExactTripCount() {
@@ -164,7 +181,7 @@
         return isConstantMaxTripCount();
     }
 
-    public long constantExactTripCount() {
+    public UnsignedLong constantExactTripCount() {
         assert isExactTripCount();
         return constantMaxTripCount();
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/DefaultLoopPolicies.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/DefaultLoopPolicies.java	Fri Mar 16 22:59:32 2018 -0700
@@ -28,6 +28,7 @@
 
 import java.util.List;
 
+import org.graalvm.compiler.core.common.util.UnsignedLong;
 import org.graalvm.compiler.debug.CounterKey;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.graph.Node;
@@ -89,11 +90,22 @@
         }
         OptionValues options = loop.entryPoint().getOptions();
         CountedLoopInfo counted = loop.counted();
-        long maxTrips = counted.constantMaxTripCount();
+        UnsignedLong maxTrips = counted.constantMaxTripCount();
+        if (maxTrips.equals(0)) {
+            return loop.canDuplicateLoop();
+        }
         int maxNodes = (counted.isExactTripCount() && counted.isConstantExactTripCount()) ? Options.ExactFullUnrollMaxNodes.getValue(options) : Options.FullUnrollMaxNodes.getValue(options);
         maxNodes = Math.min(maxNodes, Math.max(0, MaximumDesiredSize.getValue(options) - loop.loopBegin().graph().getNodeCount()));
         int size = Math.max(1, loop.size() - 1 - loop.loopBegin().phis().count());
-        if (maxTrips <= Options.FullUnrollMaxIterations.getValue(options) && size * (maxTrips - 1) <= maxNodes) {
+        /* @formatter:off
+         * The check below should not throw ArithmeticException because:
+         * maxTrips is guaranteed to be >= 1 by the check above
+         * - maxTrips * size can not overfow because:
+         *   - maxTrips <= FullUnrollMaxIterations <= Integer.MAX_VALUE
+         *   - 1 <= size <= Integer.MAX_VALUE
+         * @formatter:on
+         */
+        if (maxTrips.isLessOrEqualTo(Options.FullUnrollMaxIterations.getValue(options)) && maxTrips.minus(1).times(size).isLessOrEqualTo(maxNodes)) {
             // check whether we're allowed to unroll this loop
             return loop.canDuplicateLoop();
         } else {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragment.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragment.java	Fri Mar 16 22:59:32 2018 -0700
@@ -35,6 +35,7 @@
 import org.graalvm.compiler.graph.NodeBitMap;
 import org.graalvm.compiler.graph.iterators.NodeIterable;
 import org.graalvm.compiler.nodes.AbstractBeginNode;
+import org.graalvm.compiler.nodes.AbstractMergeNode;
 import org.graalvm.compiler.nodes.EndNode;
 import org.graalvm.compiler.nodes.FixedNode;
 import org.graalvm.compiler.nodes.FrameState;
@@ -208,6 +209,12 @@
                     NodeWithState withState = (NodeWithState) n;
                     withState.states().forEach(state -> state.applyToVirtual(node -> nodes.mark(node)));
                 }
+                if (n instanceof AbstractMergeNode) {
+                    // if a merge is in the loop, all of its phis are also in the loop
+                    for (PhiNode phi : ((AbstractMergeNode) n).phis()) {
+                        nodes.mark(phi);
+                    }
+                }
                 nodes.mark(n);
             }
         }
@@ -246,6 +253,17 @@
                 if (n instanceof MonitorEnterNode) {
                     markFloating(worklist, ((MonitorEnterNode) n).getMonitorId(), nodes, nonLoopNodes);
                 }
+                if (n instanceof AbstractMergeNode) {
+                    /*
+                     * Since we already marked all phi nodes as being in the loop to break cycles,
+                     * we also have to iterate over their usages here.
+                     */
+                    for (PhiNode phi : ((AbstractMergeNode) n).phis()) {
+                        for (Node usage : phi.usages()) {
+                            markFloating(worklist, usage, nodes, nonLoopNodes);
+                        }
+                    }
+                }
                 for (Node usage : n.usages()) {
                     markFloating(worklist, usage, nodes, nonLoopNodes);
                 }
@@ -263,6 +281,20 @@
             this.usages = n.usages().iterator();
             this.isLoopNode = loopNodes.isMarked(n);
         }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof WorkListEntry)) {
+                return false;
+            }
+            WorkListEntry other = (WorkListEntry) obj;
+            return this.n == other.n;
+        }
+
+        @Override
+        public int hashCode() {
+            return n.hashCode();
+        }
     }
 
     static TriState isLoopNode(Node n, NodeBitMap loopNodes, NodeBitMap nonLoopNodes) {
@@ -272,32 +304,24 @@
         if (nonLoopNodes.isMarked(n)) {
             return TriState.FALSE;
         }
-        if (n instanceof FixedNode) {
+        if (n instanceof FixedNode || n instanceof PhiNode) {
+            // phi nodes are treated the same as fixed nodes in this algorithm to break cycles
             return TriState.FALSE;
         }
-        boolean mark = false;
-        if (n instanceof PhiNode) {
-            PhiNode phi = (PhiNode) n;
-            mark = loopNodes.isMarked(phi.merge());
-            if (mark) {
-                /*
-                 * This Phi is a loop node but the inputs might not be so they must be processed by
-                 * the caller.
-                 */
-                loopNodes.mark(n);
-            } else {
-                nonLoopNodes.mark(n);
-                return TriState.FALSE;
-            }
-        }
         return TriState.UNKNOWN;
     }
 
+    private static void pushWorkList(Deque<WorkListEntry> workList, Node node, NodeBitMap loopNodes) {
+        WorkListEntry entry = new WorkListEntry(node, loopNodes);
+        assert !workList.contains(entry) : "node " + node + " added to worklist twice";
+        workList.push(entry);
+    }
+
     private static void markFloating(Deque<WorkListEntry> workList, Node start, NodeBitMap loopNodes, NodeBitMap nonLoopNodes) {
         if (isLoopNode(start, loopNodes, nonLoopNodes).isKnown()) {
             return;
         }
-        workList.push(new WorkListEntry(start, loopNodes));
+        pushWorkList(workList, start, loopNodes);
         while (!workList.isEmpty()) {
             WorkListEntry currentEntry = workList.peek();
             if (currentEntry.usages.hasNext()) {
@@ -308,7 +332,7 @@
                         currentEntry.isLoopNode = true;
                     }
                 } else {
-                    workList.push(new WorkListEntry(current, loopNodes));
+                    pushWorkList(workList, current, loopNodes);
                 }
             } else {
                 workList.pop();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentInside.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentInside.java	Fri Mar 16 22:59:32 2018 -0700
@@ -28,6 +28,7 @@
 
 import org.graalvm.collections.EconomicMap;
 import org.graalvm.collections.Equivalence;
+import org.graalvm.compiler.debug.DebugCloseable;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.graph.Graph.DuplicationReplacement;
@@ -338,6 +339,7 @@
     }
 
     @Override
+    @SuppressWarnings("try")
     protected DuplicationReplacement getDuplicationReplacement() {
         final LoopBeginNode loopBegin = loop().loopBegin();
         final StructuredGraph graph = graph();
@@ -347,34 +349,36 @@
 
             @Override
             public Node replacement(Node original) {
-                if (original == loopBegin) {
-                    Node value = seenNode.get(original);
-                    if (value != null) {
-                        return value;
+                try (DebugCloseable position = original.withNodeSourcePosition()) {
+                    if (original == loopBegin) {
+                        Node value = seenNode.get(original);
+                        if (value != null) {
+                            return value;
+                        }
+                        AbstractBeginNode newValue = graph.add(new BeginNode());
+                        seenNode.put(original, newValue);
+                        return newValue;
                     }
-                    AbstractBeginNode newValue = graph.add(new BeginNode());
-                    seenNode.put(original, newValue);
-                    return newValue;
+                    if (original instanceof LoopExitNode && ((LoopExitNode) original).loopBegin() == loopBegin) {
+                        Node value = seenNode.get(original);
+                        if (value != null) {
+                            return value;
+                        }
+                        AbstractBeginNode newValue = graph.add(new BeginNode());
+                        seenNode.put(original, newValue);
+                        return newValue;
+                    }
+                    if (original instanceof LoopEndNode && ((LoopEndNode) original).loopBegin() == loopBegin) {
+                        Node value = seenNode.get(original);
+                        if (value != null) {
+                            return value;
+                        }
+                        EndNode newValue = graph.add(new EndNode());
+                        seenNode.put(original, newValue);
+                        return newValue;
+                    }
+                    return original;
                 }
-                if (original instanceof LoopExitNode && ((LoopExitNode) original).loopBegin() == loopBegin) {
-                    Node value = seenNode.get(original);
-                    if (value != null) {
-                        return value;
-                    }
-                    AbstractBeginNode newValue = graph.add(new BeginNode());
-                    seenNode.put(original, newValue);
-                    return newValue;
-                }
-                if (original instanceof LoopEndNode && ((LoopEndNode) original).loopBegin() == loopBegin) {
-                    Node value = seenNode.get(original);
-                    if (value != null) {
-                        return value;
-                    }
-                    EndNode newValue = graph.add(new EndNode());
-                    seenNode.put(original, newValue);
-                    return newValue;
-                }
-                return original;
             }
         };
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/MathUtil.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/MathUtil.java	Fri Mar 16 22:59:32 2018 -0700
@@ -30,6 +30,9 @@
 import org.graalvm.compiler.nodes.calc.BinaryArithmeticNode;
 import org.graalvm.compiler.nodes.calc.FixedBinaryNode;
 import org.graalvm.compiler.nodes.calc.SignedDivNode;
+import org.graalvm.compiler.nodes.calc.UnsignedDivNode;
+
+import java.util.function.BiFunction;
 
 /**
  * Utility methods to perform integer math with some obvious constant folding first.
@@ -71,12 +74,28 @@
     }
 
     public static ValueNode divBefore(StructuredGraph graph, FixedNode before, ValueNode dividend, ValueNode divisor) {
+        return fixedDivBefore(graph, before, dividend, divisor, (dend, sor) -> SignedDivNode.create(dend, sor, NodeView.DEFAULT));
+    }
+
+    public static ValueNode unsignedDivBefore(StructuredGraph graph, FixedNode before, ValueNode dividend, ValueNode divisor) {
+        return fixedDivBefore(graph, before, dividend, divisor, (dend, sor) -> UnsignedDivNode.create(dend, sor, NodeView.DEFAULT));
+    }
+
+    private static ValueNode fixedDivBefore(StructuredGraph graph, FixedNode before, ValueNode dividend, ValueNode divisor, BiFunction<ValueNode, ValueNode, ValueNode> createDiv) {
         if (isConstantOne(divisor)) {
             return dividend;
         }
-        ValueNode div = graph.addOrUniqueWithInputs(SignedDivNode.create(dividend, divisor, NodeView.DEFAULT));
+        ValueNode div = graph.addOrUniqueWithInputs(createDiv.apply(dividend, divisor));
         if (div instanceof FixedBinaryNode) {
-            graph.addBeforeFixed(before, (FixedBinaryNode) div);
+            FixedBinaryNode fixedDiv = (FixedBinaryNode) div;
+            if (before.predecessor() instanceof FixedBinaryNode) {
+                FixedBinaryNode binaryPredecessor = (FixedBinaryNode) before.predecessor();
+                if (fixedDiv.dataFlowEquals(binaryPredecessor)) {
+                    fixedDiv.safeDelete();
+                    return binaryPredecessor;
+                }
+            }
+            graph.addBeforeFixed(before, fixedDiv);
         }
         return div;
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/IntegerStampTest.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/IntegerStampTest.java	Fri Mar 16 22:59:32 2018 -0700
@@ -570,4 +570,16 @@
         assertEquals(IntegerStamp.create(bits, 0, 1000), div.foldStamp(IntegerStamp.create(bits, 100, 1000), IntegerStamp.create(bits, 1, max)));
         assertEquals(IntegerStamp.create(bits, -1000, 0), div.foldStamp(IntegerStamp.create(bits, -1000, -100), IntegerStamp.create(bits, 1, max)));
     }
+
+    @Test
+    public void testEmpty() {
+        IntegerStamp intStamp = StampFactory.forInteger(32);
+        IntegerStamp longStamp = StampFactory.forInteger(64);
+        Stamp intEmpty = StampFactory.empty(JavaKind.Int);
+        Stamp longEmpty = StampFactory.empty(JavaKind.Long);
+        assertEquals(intStamp.join(intEmpty), intEmpty);
+        assertEquals(intStamp.meet(intEmpty), intStamp);
+        assertEquals(longStamp.join(longEmpty), longEmpty);
+        assertEquals(longStamp.meet(longEmpty), longStamp);
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/PrimitiveStampBoundaryTest.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/PrimitiveStampBoundaryTest.java	Fri Mar 16 22:59:32 2018 -0700
@@ -35,6 +35,7 @@
 import org.graalvm.compiler.core.common.type.IntegerStamp;
 import org.graalvm.compiler.core.common.type.PrimitiveStamp;
 import org.graalvm.compiler.core.common.type.Stamp;
+import org.graalvm.compiler.core.common.type.StampFactory;
 import org.graalvm.compiler.test.GraalTest;
 import org.junit.Test;
 
@@ -64,6 +65,7 @@
                 shiftStamps.add(IntegerStamp.create(32, Math.min(v1, v2), Math.max(v1, v2)));
             }
         }
+        shiftStamps.add((IntegerStamp) StampFactory.empty(JavaKind.Int));
 
         integerTestStamps = new HashSet<>();
         for (long v1 : longBoundaryValues) {
@@ -74,6 +76,8 @@
                 integerTestStamps.add(IntegerStamp.create(64, Math.min(v1, v2), Math.max(v1, v2)));
             }
         }
+        integerTestStamps.add((PrimitiveStamp) StampFactory.empty(JavaKind.Int));
+        integerTestStamps.add((PrimitiveStamp) StampFactory.empty(JavaKind.Long));
     }
 
     static double[] doubleBoundaryValues = {Double.NEGATIVE_INFINITY, Double.MIN_VALUE, Float.NEGATIVE_INFINITY, Float.MIN_VALUE,
@@ -98,6 +102,8 @@
                 generateFloatingStamps(new FloatStamp(64, Math.min(d1, d2), Math.max(d1, d2), false));
             }
         }
+        floatTestStamps.add((PrimitiveStamp) StampFactory.empty(JavaKind.Float));
+        floatTestStamps.add((PrimitiveStamp) StampFactory.empty(JavaKind.Double));
     }
 
     private static void generateFloatingStamps(FloatStamp floatStamp) {
@@ -130,7 +136,7 @@
 
     private static void checkConvertOperation(IntegerConvertOp<?> op, int inputBits, int resultBits, Stamp result, Stamp v1stamp) {
         Stamp folded = op.foldStamp(inputBits, resultBits, v1stamp);
-        assertTrue(folded.asConstant() != null, "should constant fold %s %s %s", op, v1stamp, folded);
+        assertTrue(folded.isEmpty() || folded.asConstant() != null, "should constant fold %s %s %s", op, v1stamp, folded);
         assertTrue(result.meet(folded).equals(result), "result out of range %s %s %s %s %s", op, v1stamp, folded, result, result.meet(folded));
     }
 
@@ -167,7 +173,7 @@
 
     private static void checkConvertOperation(ArithmeticOpTable.FloatConvertOp op, Stamp result, Stamp v1stamp) {
         Stamp folded = op.foldStamp(v1stamp);
-        assertTrue(folded.asConstant() != null, "should constant fold %s %s %s", op, v1stamp, folded);
+        assertTrue(folded.isEmpty() || folded.asConstant() != null, "should constant fold %s %s %s", op, v1stamp, folded);
         assertTrue(result.meet(folded).equals(result), "result out of range %s %s %s %s %s", op, v1stamp, folded, result, result.meet(folded));
     }
 
@@ -184,6 +190,10 @@
                 IntegerStamp stamp = (IntegerStamp) testStamp;
                 for (IntegerStamp shiftStamp : shifts) {
                     IntegerStamp foldedStamp = (IntegerStamp) shiftOp.foldStamp(stamp, shiftStamp);
+                    if (foldedStamp.isEmpty()) {
+                        assertTrue(stamp.isEmpty() || shiftStamp.isEmpty());
+                        continue;
+                    }
                     checkShiftOperation(stamp.getBits(), shiftOp, foldedStamp, stamp.lowerBound(), shiftStamp.lowerBound());
                     checkShiftOperation(stamp.getBits(), shiftOp, foldedStamp, stamp.lowerBound(), shiftStamp.upperBound());
                     checkShiftOperation(stamp.getBits(), shiftOp, foldedStamp, stamp.upperBound(), shiftStamp.lowerBound());
@@ -205,8 +215,15 @@
 
     private static void checkBinaryOperation(ArithmeticOpTable.BinaryOp<?> op, Stamp result, Stamp v1stamp, Stamp v2stamp) {
         Stamp folded = op.foldStamp(v1stamp, v2stamp);
+        if (v1stamp.isEmpty() || v2stamp.isEmpty()) {
+            assertTrue(folded.isEmpty());
+            assertTrue(v1stamp.asConstant() != null || v1stamp.isEmpty());
+            assertTrue(v2stamp.asConstant() != null || v2stamp.isEmpty());
+            return;
+        }
         Constant constant = op.foldConstant(v1stamp.asConstant(), v2stamp.asConstant());
         if (constant != null) {
+            assertFalse(folded.isEmpty());
             Constant constant2 = folded.asConstant();
             if (constant2 == null && v1stamp instanceof FloatStamp) {
                 JavaConstant c = (JavaConstant) constant;
@@ -239,6 +256,9 @@
     }
 
     private static Stamp boundaryStamp(Stamp v1, boolean upper) {
+        if (v1.isEmpty()) {
+            return v1;
+        }
         if (v1 instanceof IntegerStamp) {
             IntegerStamp istamp = (IntegerStamp) v1;
             long bound = upper ? istamp.upperBound() : istamp.lowerBound();
@@ -319,7 +339,7 @@
                 }
             }
         } else {
-            assert v1stamp instanceof FloatStamp;
+            assertTrue(v1stamp.isEmpty() || v1stamp instanceof FloatStamp);
         }
         assertTrue(result.meet(folded).equals(result), "result out of range %s %s %s %s %s", op, v1stamp, folded, result, result.meet(folded));
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/AbstractFixedGuardNode.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/AbstractFixedGuardNode.java	Fri Mar 16 22:59:32 2018 -0700
@@ -23,6 +23,7 @@
 package org.graalvm.compiler.nodes;
 
 import org.graalvm.compiler.core.common.type.StampFactory;
+import org.graalvm.compiler.debug.DebugCloseable;
 import org.graalvm.compiler.graph.NodeClass;
 import org.graalvm.compiler.graph.spi.Simplifiable;
 import org.graalvm.compiler.graph.spi.SimplifierTool;
@@ -41,8 +42,8 @@
 
     public static final NodeClass<AbstractFixedGuardNode> TYPE = NodeClass.create(AbstractFixedGuardNode.class);
     @Input(InputType.Condition) protected LogicNode condition;
-    protected final DeoptimizationReason reason;
-    protected final DeoptimizationAction action;
+    protected DeoptimizationReason reason;
+    protected DeoptimizationAction action;
     protected JavaConstant speculation;
     protected boolean negated;
 
@@ -109,29 +110,42 @@
         }
     }
 
+    @SuppressWarnings("try")
     public DeoptimizeNode lowerToIf() {
-        FixedNode currentNext = next();
-        setNext(null);
-        DeoptimizeNode deopt = graph().add(new DeoptimizeNode(action, reason, speculation));
-        deopt.setStateBefore(stateBefore());
-        IfNode ifNode;
-        AbstractBeginNode noDeoptSuccessor;
-        if (negated) {
-            ifNode = graph().add(new IfNode(condition, deopt, currentNext, 0));
-            noDeoptSuccessor = ifNode.falseSuccessor();
-        } else {
-            ifNode = graph().add(new IfNode(condition, currentNext, deopt, 1));
-            noDeoptSuccessor = ifNode.trueSuccessor();
+        try (DebugCloseable position = this.withNodeSourcePosition()) {
+            FixedNode currentNext = next();
+            setNext(null);
+            DeoptimizeNode deopt = graph().add(new DeoptimizeNode(action, reason, speculation));
+            deopt.setStateBefore(stateBefore());
+            IfNode ifNode;
+            AbstractBeginNode noDeoptSuccessor;
+            if (negated) {
+                ifNode = graph().add(new IfNode(condition, deopt, currentNext, 0));
+                noDeoptSuccessor = ifNode.falseSuccessor();
+            } else {
+                ifNode = graph().add(new IfNode(condition, currentNext, deopt, 1));
+                noDeoptSuccessor = ifNode.trueSuccessor();
+            }
+            ((FixedWithNextNode) predecessor()).setNext(ifNode);
+            this.replaceAtUsages(noDeoptSuccessor);
+            GraphUtil.killWithUnusedFloatingInputs(this);
+
+            return deopt;
         }
-        ((FixedWithNextNode) predecessor()).setNext(ifNode);
-        this.replaceAtUsages(noDeoptSuccessor);
-        GraphUtil.killWithUnusedFloatingInputs(this);
-
-        return deopt;
     }
 
     @Override
     public boolean canDeoptimize() {
         return true;
     }
+
+    @Override
+    public void setAction(DeoptimizationAction action) {
+        this.action = action;
+    }
+
+    @Override
+    public void setReason(DeoptimizationReason reason) {
+        this.reason = reason;
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/BeginNode.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/BeginNode.java	Fri Mar 16 22:59:32 2018 -0700
@@ -27,6 +27,7 @@
 
 import org.graalvm.compiler.core.common.type.Stamp;
 import org.graalvm.compiler.core.common.type.StampFactory;
+import org.graalvm.compiler.debug.DebugCloseable;
 import org.graalvm.compiler.graph.NodeClass;
 import org.graalvm.compiler.graph.spi.Simplifiable;
 import org.graalvm.compiler.graph.spi.SimplifierTool;
@@ -71,12 +72,15 @@
         }
     }
 
+    @SuppressWarnings("try")
     public static AbstractBeginNode begin(FixedNode with) {
-        if (with instanceof AbstractBeginNode) {
-            return (AbstractBeginNode) with;
+        try (DebugCloseable position = with.withNodeSourcePosition()) {
+            if (with instanceof AbstractBeginNode) {
+                return (AbstractBeginNode) with;
+            }
+            BeginNode begin = with.graph().add(new BeginNode());
+            begin.setNext(with);
+            return begin;
         }
-        BeginNode begin = with.graph().add(new BeginNode());
-        begin.setNext(with);
-        return begin;
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/DeoptimizeNode.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/DeoptimizeNode.java	Fri Mar 16 22:59:32 2018 -0700
@@ -43,8 +43,8 @@
     public static final int DEFAULT_DEBUG_ID = 0;
 
     public static final NodeClass<DeoptimizeNode> TYPE = NodeClass.create(DeoptimizeNode.class);
-    protected final DeoptimizationAction action;
-    protected final DeoptimizationReason reason;
+    protected DeoptimizationAction action;
+    protected DeoptimizationReason reason;
     protected int debugId;
     protected final JavaConstant speculation;
 
@@ -73,11 +73,21 @@
     }
 
     @Override
+    public void setAction(DeoptimizationAction action) {
+        this.action = action;
+    }
+
+    @Override
     public DeoptimizationReason getReason() {
         return reason;
     }
 
     @Override
+    public void setReason(DeoptimizationReason reason) {
+        this.reason = reason;
+    }
+
+    @Override
     public void lower(LoweringTool tool) {
         tool.getLowerer().lower(this, tool);
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/DynamicPiNode.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/DynamicPiNode.java	Fri Mar 16 22:59:32 2018 -0700
@@ -31,6 +31,8 @@
 import org.graalvm.compiler.nodeinfo.NodeInfo;
 import org.graalvm.compiler.nodes.extended.GuardingNode;
 
+import jdk.vm.ci.meta.Assumptions;
+import jdk.vm.ci.meta.ConstantReflectionProvider;
 import jdk.vm.ci.meta.ResolvedJavaType;
 
 /**
@@ -42,29 +44,55 @@
 
     public static final NodeClass<DynamicPiNode> TYPE = NodeClass.create(DynamicPiNode.class);
     @Input ValueNode typeMirror;
+    private final boolean exact;
 
-    public DynamicPiNode(ValueNode object, GuardingNode guard, ValueNode typeMirror) {
+    protected DynamicPiNode(ValueNode object, GuardingNode guard, ValueNode typeMirror, boolean exact) {
         super(TYPE, object, StampFactory.object(), guard);
         this.typeMirror = typeMirror;
+        this.exact = exact;
     }
 
-    @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public static ValueNode create(Assumptions assumptions, ConstantReflectionProvider constantReflection, ValueNode object, GuardingNode guard, ValueNode typeMirror, boolean exact) {
+        ValueNode synonym = findSynonym(assumptions, constantReflection, object, guard, typeMirror, exact);
+        if (synonym != null) {
+            return synonym;
+        }
+        return new DynamicPiNode(object, guard, typeMirror, exact);
+    }
+
+    public static ValueNode create(Assumptions assumptions, ConstantReflectionProvider constantReflection, ValueNode object, GuardingNode guard, ValueNode typeMirror) {
+        return create(assumptions, constantReflection, object, guard, typeMirror, false);
+    }
+
+    public boolean isExact() {
+        return exact;
+    }
+
+    private static ValueNode findSynonym(Assumptions assumptions, ConstantReflectionProvider constantReflection, ValueNode object, GuardingNode guard, ValueNode typeMirror, boolean exact) {
         if (typeMirror.isConstant()) {
-            ResolvedJavaType t = tool.getConstantReflection().asJavaType(typeMirror.asConstant());
+            ResolvedJavaType t = constantReflection.asJavaType(typeMirror.asConstant());
             if (t != null) {
                 Stamp staticPiStamp;
                 if (t.isPrimitive()) {
                     staticPiStamp = StampFactory.alwaysNull();
                 } else {
-                    TypeReference type = TypeReference.createTrusted(tool.getAssumptions(), t);
+                    TypeReference type = exact ? TypeReference.createExactTrusted(t) : TypeReference.createTrusted(assumptions, t);
                     staticPiStamp = StampFactory.object(type);
                 }
 
-                return new PiNode(object(), staticPiStamp, (ValueNode) getGuard()).canonical(tool);
+                return PiNode.create(object, staticPiStamp, (ValueNode) guard);
             }
         }
 
+        return null;
+    }
+
+    @Override
+    public Node canonical(CanonicalizerTool tool) {
+        ValueNode synonym = findSynonym(tool.getAssumptions(), tool.getConstantReflection(), object, guard, typeMirror, exact);
+        if (synonym != null) {
+            return synonym;
+        }
         return this;
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/EncodedGraph.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/EncodedGraph.java	Fri Mar 16 22:59:32 2018 -0700
@@ -24,9 +24,11 @@
 
 import java.util.List;
 
+import org.graalvm.collections.EconomicSet;
 import org.graalvm.compiler.graph.NodeClass;
 
 import jdk.vm.ci.meta.Assumptions;
+import jdk.vm.ci.meta.ResolvedJavaField;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 
 /**
@@ -34,7 +36,7 @@
  * {@link GraphEncoder} for a description of the encoding format. Use {@link GraphDecoder} for
  * decoding.
  */
-public class EncodedGraph {
+public final class EncodedGraph {
 
     private final byte[] encoding;
     private final int startOffset;
@@ -42,6 +44,9 @@
     private final NodeClass<?>[] types;
     private final Assumptions assumptions;
     private final List<ResolvedJavaMethod> inlinedMethods;
+    private final boolean trackNodeSourcePosition;
+    private final EconomicSet<ResolvedJavaField> fields;
+    private final boolean hasUnsafeAccess;
 
     /**
      * The "table of contents" of the encoded graph, i.e., the mapping from orderId numbers to the
@@ -49,13 +54,22 @@
      */
     protected int[] nodeStartOffsets;
 
-    public EncodedGraph(byte[] encoding, int startOffset, Object[] objects, NodeClass<?>[] types, Assumptions assumptions, List<ResolvedJavaMethod> inlinedMethods) {
+    public EncodedGraph(byte[] encoding, int startOffset, Object[] objects, NodeClass<?>[] types, StructuredGraph sourceGraph) {
+        this(encoding, startOffset, objects, types, sourceGraph.getAssumptions(), sourceGraph.getMethods(), sourceGraph.getFields(), sourceGraph.hasUnsafeAccess(),
+                        sourceGraph.trackNodeSourcePosition());
+    }
+
+    public EncodedGraph(byte[] encoding, int startOffset, Object[] objects, NodeClass<?>[] types, Assumptions assumptions, List<ResolvedJavaMethod> inlinedMethods,
+                    EconomicSet<ResolvedJavaField> fields, boolean hasUnsafeAccess, boolean trackNodeSourcePosition) {
         this.encoding = encoding;
         this.startOffset = startOffset;
         this.objects = objects;
         this.types = types;
         this.assumptions = assumptions;
         this.inlinedMethods = inlinedMethods;
+        this.trackNodeSourcePosition = trackNodeSourcePosition;
+        this.fields = fields;
+        this.hasUnsafeAccess = hasUnsafeAccess;
     }
 
     public byte[] getEncoding() {
@@ -81,4 +95,16 @@
     public List<ResolvedJavaMethod> getInlinedMethods() {
         return inlinedMethods;
     }
+
+    public boolean trackNodeSourcePosition() {
+        return trackNodeSourcePosition;
+    }
+
+    public EconomicSet<ResolvedJavaField> getFields() {
+        return fields;
+    }
+
+    public boolean hasUnsafeAccess() {
+        return hasUnsafeAccess;
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedGuardNode.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedGuardNode.java	Fri Mar 16 22:59:32 2018 -0700
@@ -22,6 +22,7 @@
  */
 package org.graalvm.compiler.nodes;
 
+import org.graalvm.compiler.debug.DebugCloseable;
 import static org.graalvm.compiler.nodeinfo.InputType.Guard;
 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2;
 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_2;
@@ -80,16 +81,19 @@
         }
     }
 
+    @SuppressWarnings("try")
     @Override
     public void lower(LoweringTool tool) {
-        if (graph().getGuardsStage().allowsFloatingGuards()) {
-            if (getAction() != DeoptimizationAction.None) {
-                ValueNode guard = tool.createGuard(this, getCondition(), getReason(), getAction(), getSpeculation(), isNegated()).asNode();
-                this.replaceAtUsages(guard);
-                graph().removeFixed(this);
+        try (DebugCloseable position = this.withNodeSourcePosition()) {
+            if (graph().getGuardsStage().allowsFloatingGuards()) {
+                if (getAction() != DeoptimizationAction.None) {
+                    ValueNode guard = tool.createGuard(this, getCondition(), getReason(), getAction(), getSpeculation(), isNegated()).asNode();
+                    this.replaceAtUsages(guard);
+                    graph().removeFixed(this);
+                }
+            } else {
+                lowerToIf().lower(tool);
             }
-        } else {
-            lowerToIf().lower(tool);
         }
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FrameState.java	Fri Mar 16 11:26:05 2018 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compile