changeset 6525:2c913b643422

rename packages in graal.phases to match project name
author Doug Simon <doug.simon@oracle.com>
date Sun, 07 Oct 2012 14:15:44 +0200
parents a206e077ffc8
children ee651c726397
files graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/MethodElement.java graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/target/amd64/AMD64DeoptimizationStub.java graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompiledMethodTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraphScheduleTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfBoxingEliminationTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/IntervalWalker.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/MoveResolver.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/RegisterVerifier.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerThread.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/DebugFilter.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugConfig.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphCache.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/InstanceOfSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/IntrinsifyArrayCopyPhase.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopFullUnrollPhase.java graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformHighPhase.java graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/GraalOptions.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/OptimisticOptimizations.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/graph/MergeableState.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/graph/PostOrderNodeIterator.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/graph/package-info.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/package-info.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/BoxingEliminationPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/CanonicalizerPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/CheckCastEliminationPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/ComputeProbabilityPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/ConvertDeoptimizeToGuardPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/ConvertUnreachedToGuardPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/CullFrameStatesPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/DeadCodeEliminationPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/ExpandBoxingNodesPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/FloatingReadPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/GlobalValueNumberingPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/IdentifyBoxingPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/InliningPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/InsertStateAfterPlaceholderPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/IntrinsificationPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/IterativeCheckCastEliminationPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/LoopSafepointInsertionPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/LoweringPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/Phase.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/PhasePlan.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/PhiStampPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/ReadEliminationPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/RemoveValueProxyPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/TailDuplicationPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/schedule/BlockClosure.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/schedule/SchedulePhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/util/ArrayMap.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/util/BitMap2D.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/util/BlockWorkList.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/util/GraphOrder.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/util/InliningUtil.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/util/IntList.java graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/util/Util.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/OptimisticOptimizations.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/MergeableState.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/PostOrderNodeIterator.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/package-info.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/package-info.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/BoxingEliminationPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/CanonicalizerPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/CheckCastEliminationPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/ComputeProbabilityPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/ConvertDeoptimizeToGuardPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/ConvertUnreachedToGuardPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/CullFrameStatesPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/DeadCodeEliminationPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/ExpandBoxingNodesPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/FloatingReadPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/GlobalValueNumberingPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/IdentifyBoxingPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/InliningPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/InsertStateAfterPlaceholderPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/IntrinsificationPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/IterativeCheckCastEliminationPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/LoopSafepointInsertionPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/LoweringPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/Phase.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/PhasePlan.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/PhiStampPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/ReadEliminationPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/RemoveValueProxyPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/TailDuplicationPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/BlockClosure.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/ArrayMap.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/BitMap2D.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/BlockWorkList.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/InliningUtil.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/IntList.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/Util.java graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinter.java graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/InstanceOfTest.java graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/InvokeTest.java graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/WordTest.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/GraalIntrinsics.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationPhase.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetVerificationPhase.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/experimental/SplitPartialEscapeAnalysisPhase.java
diffstat 153 files changed, 7102 insertions(+), 7096 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/MethodElement.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/MethodElement.java	Sun Oct 07 14:15:44 2012 +0200
@@ -27,13 +27,13 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.boot.*;
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.java.*;
 import com.oracle.graal.java.GraphBuilderConfiguration.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.phases.*;
 
 
 public class MethodElement extends Element {
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/target/amd64/AMD64DeoptimizationStub.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/target/amd64/AMD64DeoptimizationStub.java	Sun Oct 07 14:15:44 2012 +0200
@@ -27,10 +27,10 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.RuntimeCall.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.phases.*;
 import com.oracle.max.asm.*;
 import com.oracle.max.asm.amd64.*;
 
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java	Sun Oct 07 14:15:44 2012 +0200
@@ -32,7 +32,6 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
-import com.oracle.graal.compiler.util.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.JumpOp;
@@ -69,6 +68,7 @@
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.phases.util.*;
 import com.oracle.max.asm.*;
 import com.oracle.max.asm.amd64.*;
 import com.oracle.max.asm.amd64.AMD64Assembler.ConditionFlag;
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java	Sun Oct 07 14:15:44 2012 +0200
@@ -26,12 +26,12 @@
 
 import org.junit.*;
 
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.phases.*;
-import com.oracle.graal.compiler.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.phases.*;
+import com.oracle.graal.phases.phases.PhasePlan.*;
 
 /**
  * In the following tests, the usages of local variable "a" are replaced with the integer constant 0. Then boxing
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java	Sun Oct 07 14:15:44 2012 +0200
@@ -24,8 +24,8 @@
 
 import org.junit.*;
 
-import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.phases.*;
 
 public class CompareCanonicalizerTest extends GraalCompilerTest {
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompiledMethodTest.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompiledMethodTest.java	Sun Oct 07 14:15:44 2012 +0200
@@ -29,11 +29,11 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.InstalledCode.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.java.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.phases.*;
 
 /**
  * In the following tests, the usages of local variable "a" are replaced with the integer constant 0. Then
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java	Sun Oct 07 14:15:44 2012 +0200
@@ -24,9 +24,9 @@
 
 import org.junit.*;
 
-import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.phases.*;
 
 /**
  * In the following tests, the usages of local variable "a" are replaced with the integer constant 0.
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java	Sun Oct 07 14:15:44 2012 +0200
@@ -24,11 +24,11 @@
 
 import org.junit.*;
 
-import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.phases.phases.*;
 
 public class FloatingReadTest extends GraphScheduleTest {
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Sun Oct 07 14:15:44 2012 +0200
@@ -32,9 +32,6 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.phases.*;
-import com.oracle.graal.compiler.phases.PhasePlan.PhasePosition;
-import com.oracle.graal.compiler.schedule.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.Verbosity;
@@ -42,6 +39,10 @@
 import com.oracle.graal.lir.cfg.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.phases.*;
+import com.oracle.graal.phases.phases.PhasePlan.*;
+import com.oracle.graal.phases.schedule.*;
 
 /**
  * Base class for Graal compiler unit tests. These are white box tests
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraphScheduleTest.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraphScheduleTest.java	Sun Oct 07 14:15:44 2012 +0200
@@ -26,10 +26,10 @@
 
 import org.junit.*;
 
-import com.oracle.graal.compiler.schedule.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.cfg.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.schedule.*;
 
 public class GraphScheduleTest extends GraalCompilerTest {
     protected void assertOrderedAfterSchedule(StructuredGraph graph, Node a, Node b) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfBoxingEliminationTest.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfBoxingEliminationTest.java	Sun Oct 07 14:15:44 2012 +0200
@@ -26,12 +26,12 @@
 
 import org.junit.*;
 
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.phases.*;
-import com.oracle.graal.compiler.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.phases.*;
+import com.oracle.graal.phases.phases.PhasePlan.*;
 
 public class IfBoxingEliminationTest extends GraalCompilerTest {
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java	Sun Oct 07 14:15:44 2012 +0200
@@ -26,10 +26,10 @@
 
 import org.junit.*;
 
-import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.phases.*;
 
 /**
  * In the following tests, the usages of local variable "a" are replaced with the integer constant 0.
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java	Sun Oct 07 14:15:44 2012 +0200
@@ -26,9 +26,9 @@
 
 import org.junit.*;
 
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.phases.*;
 
 public class InvokeExceptionTest extends GraalCompilerTest {
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java	Sun Oct 07 14:15:44 2012 +0200
@@ -26,9 +26,9 @@
 
 import org.junit.*;
 
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.phases.*;
 
 public class InvokeHintsTest extends GraalCompilerTest {
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java	Sun Oct 07 14:15:44 2012 +0200
@@ -24,11 +24,11 @@
 
 import org.junit.*;
 
-import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.loop.phases.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.phases.*;
 
 public class LoopUnswitchTest extends GraalCompilerTest {
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java	Sun Oct 07 14:15:44 2012 +0200
@@ -28,12 +28,12 @@
 
 import org.junit.*;
 
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.phases.*;
 
 /**
  * In the following tests, the usages of local variable "a" are replaced with the integer constant 0.
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java	Sun Oct 07 14:15:44 2012 +0200
@@ -24,9 +24,9 @@
 
 import org.junit.*;
 
-import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.phases.*;
 
 public class ReassociateAndCanonicalTest extends GraalCompilerTest {
     public static int rnd = (int) (Math.random() * 100);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java	Sun Oct 07 14:15:44 2012 +0200
@@ -24,9 +24,9 @@
 
 import org.junit.*;
 
-import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.phases.*;
 
 /**
  * In the following tests, the scalar type system of the compiler should be complete enough to see the relation between the different conditions.
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java	Sun Oct 07 14:15:44 2012 +0200
@@ -24,9 +24,9 @@
 
 import org.junit.*;
 
-import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.phases.phases.*;
 
 /**
  * This class tests some specific patterns the stamp system should be able to canonicalize away using
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java	Sun Oct 07 14:15:44 2012 +0200
@@ -24,9 +24,9 @@
 
 import org.junit.*;
 
-import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.phases.*;
 
 public class StraighteningTest extends GraalCompilerTest {
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Sun Oct 07 14:15:44 2012 +0200
@@ -28,14 +28,14 @@
 
 import org.junit.Test;
 
-import com.oracle.graal.compiler.phases.*;
-import com.oracle.graal.compiler.schedule.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.*;
 import com.oracle.graal.lir.cfg.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.phases.phases.*;
+import com.oracle.graal.phases.schedule.*;
 
 /**
  * In the following tests, the scalar type system of the compiler should be complete enough to see the relation between the different conditions.
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Sun Oct 07 14:15:44 2012 +0200
@@ -27,12 +27,12 @@
 import org.junit.Test;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.compiler.test.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.phases.*;
 import com.oracle.graal.virtual.phases.ea.*;
 
 /**
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java	Sun Oct 07 14:15:44 2012 +0200
@@ -28,13 +28,13 @@
 
 import org.junit.Test;
 
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.compiler.test.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.phases.*;
 import com.oracle.graal.virtual.nodes.*;
 import com.oracle.graal.virtual.phases.ea.*;
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Sun Oct 07 14:15:44 2012 +0200
@@ -31,9 +31,6 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.alloc.*;
 import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.compiler.phases.*;
-import com.oracle.graal.compiler.phases.PhasePlan.PhasePosition;
-import com.oracle.graal.compiler.schedule.*;
 import com.oracle.graal.compiler.target.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.lir.*;
@@ -42,6 +39,10 @@
 import com.oracle.graal.loop.phases.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.phases.*;
+import com.oracle.graal.phases.phases.PhasePlan.*;
+import com.oracle.graal.phases.schedule.*;
 import com.oracle.graal.virtual.phases.ea.*;
 import com.oracle.graal.virtual.phases.ea.experimental.*;
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java	Sun Oct 07 14:15:44 2012 +0200
@@ -27,11 +27,12 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.util.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.util.*;
+
 import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.lir.LIRValueUtil.*;
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/IntervalWalker.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/IntervalWalker.java	Sun Oct 07 14:15:44 2012 +0200
@@ -22,11 +22,11 @@
  */
 package com.oracle.graal.compiler.alloc;
 
-import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.alloc.Interval.RegisterBinding;
 import com.oracle.graal.compiler.alloc.Interval.RegisterBindingLists;
 import com.oracle.graal.compiler.alloc.Interval.State;
 import com.oracle.graal.debug.*;
+import com.oracle.graal.phases.*;
 
 /**
  */
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Sun Oct 07 14:15:44 2012 +0200
@@ -31,12 +31,10 @@
 import com.oracle.graal.alloc.*;
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.alloc.Interval.RegisterBinding;
 import com.oracle.graal.compiler.alloc.Interval.RegisterPriority;
 import com.oracle.graal.compiler.alloc.Interval.SpillState;
 import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.compiler.util.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
@@ -46,6 +44,8 @@
 import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
 import com.oracle.graal.lir.StandardOp.MoveOp;
 import com.oracle.graal.lir.cfg.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.util.*;
 
 /**
  * An implementation of the linear scan register allocator algorithm described
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java	Sun Oct 07 14:15:44 2012 +0200
@@ -31,16 +31,16 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.Register.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.alloc.Interval.RegisterBinding;
 import com.oracle.graal.compiler.alloc.Interval.RegisterPriority;
 import com.oracle.graal.compiler.alloc.Interval.SpillState;
 import com.oracle.graal.compiler.alloc.Interval.State;
-import com.oracle.graal.compiler.util.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.*;
 import com.oracle.graal.lir.cfg.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.util.*;
 
 /**
  */
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/MoveResolver.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/MoveResolver.java	Sun Oct 07 14:15:44 2012 +0200
@@ -28,9 +28,9 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.phases.*;
 
 /**
  */
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/RegisterVerifier.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/RegisterVerifier.java	Sun Oct 07 14:15:44 2012 +0200
@@ -28,13 +28,13 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.util.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.LIRInstruction.*;
 import com.oracle.graal.lir.cfg.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.util.*;
 
 /**
  */
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Sun Oct 07 14:15:44 2012 +0200
@@ -32,8 +32,6 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.util.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
@@ -48,6 +46,8 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.virtual.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.util.*;
 import com.oracle.graal.virtual.nodes.*;
 import com.oracle.max.asm.*;
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java	Sun Oct 07 14:15:44 2012 +0200
@@ -24,11 +24,11 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.phases.*;
 
 /**
  * The {@code Backend} class represents a compiler backend for Graal.
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Sun Oct 07 14:15:44 2012 +0200
@@ -30,7 +30,6 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.amd64.*;
 import com.oracle.graal.graph.*;
@@ -44,6 +43,7 @@
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.phases.*;
 import com.oracle.max.asm.*;
 import com.oracle.max.asm.amd64.*;
 import com.oracle.max.asm.amd64.AMD64Assembler.ConditionFlag;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java	Sun Oct 07 14:15:44 2012 +0200
@@ -26,11 +26,11 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.phases.*;
 
 
 public final class CompilationTask implements Runnable, Comparable<CompilationTask> {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerThread.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerThread.java	Sun Oct 07 14:15:44 2012 +0200
@@ -25,8 +25,8 @@
 import java.io.*;
 import java.util.concurrent.*;
 
-import com.oracle.graal.compiler.*;
 import com.oracle.graal.debug.*;
+import com.oracle.graal.phases.*;
 
 
 public final class CompilerThread extends Thread {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/DebugFilter.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/DebugFilter.java	Sun Oct 07 14:15:44 2012 +0200
@@ -27,9 +27,9 @@
 import java.util.*;
 import java.util.regex.*;
 
-import com.oracle.graal.compiler.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.internal.*;
+import com.oracle.graal.phases.*;
 
 /**
  * Implements the filter specified by the {@link GraalOptions#Dump},
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugConfig.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugConfig.java	Sun Oct 07 14:15:44 2012 +0200
@@ -27,10 +27,10 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.phases.*;
 import com.oracle.graal.printer.*;
 
 public class HotSpotDebugConfig implements DebugConfig {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java	Sun Oct 07 14:15:44 2012 +0200
@@ -33,6 +33,7 @@
 import com.oracle.graal.hotspot.logging.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.phases.*;
 
 /**
  * Singleton class holding the instance of the {@link GraalRuntime}.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java	Sun Oct 07 14:15:44 2012 +0200
@@ -26,8 +26,8 @@
 import java.lang.reflect.*;
 import java.util.*;
 
-import com.oracle.graal.compiler.*;
 import com.oracle.graal.hotspot.logging.*;
+import com.oracle.graal.phases.*;
 
 public class HotSpotOptions {
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompiler.java	Sun Oct 07 14:15:44 2012 +0200
@@ -26,9 +26,9 @@
 import java.io.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.phases.*;
 
 /**
  * Calls from HotSpot into Java.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java	Sun Oct 07 14:15:44 2012 +0200
@@ -31,14 +31,15 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.phases.*;
-import com.oracle.graal.compiler.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.internal.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.snippets.*;
 import com.oracle.graal.java.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.phases.*;
+import com.oracle.graal.phases.phases.PhasePlan.*;
 import com.oracle.graal.snippets.*;
 
 /**
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphCache.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphCache.java	Sun Oct 07 14:15:44 2012 +0200
@@ -28,9 +28,9 @@
 import java.util.Map.Entry;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.phases.*;
 
 /**
  * This class implements the graph caching system for the HotSpot platform.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java	Sun Oct 07 14:15:44 2012 +0200
@@ -28,8 +28,8 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.JavaTypeProfile.*;
-import com.oracle.graal.compiler.*;
 import com.oracle.graal.hotspot.*;
+import com.oracle.graal.phases.*;
 
 
 public final class HotSpotMethodData extends CompilerObject {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Sun Oct 07 14:15:44 2012 +0200
@@ -28,8 +28,8 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.JavaType.*;
-import com.oracle.graal.compiler.*;
 import com.oracle.graal.hotspot.*;
+import com.oracle.graal.phases.*;
 
 /**
  * Represents a field in a HotSpot type.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java	Sun Oct 07 14:15:44 2012 +0200
@@ -29,8 +29,8 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.bytecode.*;
-import com.oracle.graal.compiler.*;
 import com.oracle.graal.hotspot.*;
+import com.oracle.graal.phases.*;
 
 /**
  * Implementation of {@link JavaMethod} for resolved HotSpot methods.
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Sun Oct 07 14:15:44 2012 +0200
@@ -44,7 +44,6 @@
 import com.oracle.graal.api.code.RuntimeCall.Descriptor;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.JavaType.Representation;
-import com.oracle.graal.compiler.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.bridge.*;
@@ -57,6 +56,7 @@
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.phases.*;
 import com.oracle.graal.snippets.*;
 
 /**
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java	Sun Oct 07 14:15:44 2012 +0200
@@ -27,7 +27,6 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
@@ -35,6 +34,7 @@
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.phases.*;
 import com.oracle.graal.snippets.*;
 import com.oracle.graal.snippets.Snippet.ConstantParameter;
 import com.oracle.graal.snippets.Snippet.Parameter;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/InstanceOfSnippets.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/InstanceOfSnippets.java	Sun Oct 07 14:15:44 2012 +0200
@@ -30,7 +30,6 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
@@ -40,6 +39,7 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.phases.*;
 import com.oracle.graal.snippets.*;
 import com.oracle.graal.snippets.Snippet.ConstantParameter;
 import com.oracle.graal.snippets.Snippet.Parameter;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/IntrinsifyArrayCopyPhase.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/IntrinsifyArrayCopyPhase.java	Sun Oct 07 14:15:44 2012 +0200
@@ -26,14 +26,14 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.phases.*;
-import com.oracle.graal.compiler.util.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.phases.*;
+import com.oracle.graal.phases.util.*;
 
 public class IntrinsifyArrayCopyPhase extends Phase {
     private final GraalCodeCacheProvider runtime;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java	Sun Oct 07 14:15:44 2012 +0200
@@ -33,7 +33,6 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.util.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.graph.iterators.*;
@@ -43,6 +42,7 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.phases.util.*;
 import com.oracle.graal.snippets.*;
 import com.oracle.graal.snippets.Snippet.ConstantParameter;
 import com.oracle.graal.snippets.Snippet.Parameter;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java	Sun Oct 07 14:15:44 2012 +0200
@@ -31,7 +31,6 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
@@ -39,6 +38,7 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.phases.*;
 import com.oracle.graal.snippets.*;
 import com.oracle.graal.snippets.Snippet.ConstantParameter;
 import com.oracle.graal.snippets.Snippet.Parameter;
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Sun Oct 07 14:15:44 2012 +0200
@@ -29,9 +29,9 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.bytecode.*;
-import com.oracle.graal.compiler.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.*;
 
 /**
  * Builds a mapping between bytecodes and basic blocks and builds a conservative control flow graph (CFG).
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java	Sun Oct 07 14:15:44 2012 +0200
@@ -23,7 +23,7 @@
 package com.oracle.graal.java;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.phases.*;
+import com.oracle.graal.phases.phases.*;
 
 public class GraphBuilderConfiguration {
 
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Sun Oct 07 14:15:44 2012 +0200
@@ -34,9 +34,6 @@
 import com.oracle.graal.api.meta.JavaType.Representation;
 import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType;
 import com.oracle.graal.bytecode.*;
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.phases.*;
-import com.oracle.graal.compiler.util.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.java.BciBlockMapping.Block;
@@ -48,6 +45,9 @@
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.phases.*;
+import com.oracle.graal.phases.util.*;
 
 /**
  * The {@code GraphBuilder} class parses the bytecode of a method and builds the IR graph.
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopPolicies.java	Sun Oct 07 14:15:44 2012 +0200
@@ -22,10 +22,10 @@
  */
 package com.oracle.graal.loop;
 
-import com.oracle.graal.compiler.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.lir.cfg.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.*;
 
 
 public abstract class LoopPolicies {
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopTransformations.java	Sun Oct 07 14:15:44 2012 +0200
@@ -24,12 +24,12 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.phases.*;
 
 
 public abstract class LoopTransformations {
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopFullUnrollPhase.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopFullUnrollPhase.java	Sun Oct 07 14:15:44 2012 +0200
@@ -22,11 +22,11 @@
  */
 package com.oracle.graal.loop.phases;
 
-import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.loop.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.phases.phases.*;
 
 
 public class LoopFullUnrollPhase extends Phase {
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformHighPhase.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformHighPhase.java	Sun Oct 07 14:15:44 2012 +0200
@@ -22,11 +22,11 @@
  */
 package com.oracle.graal.loop.phases;
 
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.loop.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.phases.*;
 
 public class LoopTransformHighPhase extends Phase {
 
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java	Sun Oct 07 14:15:44 2012 +0200
@@ -22,11 +22,11 @@
  */
 package com.oracle.graal.loop.phases;
 
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.loop.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.phases.*;
 
 public class LoopTransformLowPhase extends Phase {
     private static final DebugMetric UNSWITCHED = Debug.metric("Unswitched");
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/GraalOptions.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,257 +0,0 @@
-/*
- * Copyright (c) 2009, 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 com.oracle.graal.compiler;
-
-
-
-/**
- * This class encapsulates options that control the behavior of the Graal compiler.
- *
- * (thomaswue) WARNING: Fields of this class are treated as final by Graal.
- */
-public final class GraalOptions {
-
-    // Checkstyle: stop
-    private static final boolean ____ = false;
-    // Checkstyle: resume
-
-    public static int     Threads                            = 4;
-
-    // inlining settings
-    public static boolean Inline                             = true;
-    public static boolean Intrinsify                         = true;
-           static boolean InlineMonomorphicCalls             = true;
-           static boolean InlinePolymorphicCalls             = true;
-           static boolean InlineMegamorphicCalls             = ____;
-    public static int     InliningPolicy                     = 4;
-    public static int     WeightComputationPolicy            = 2;
-    public static int     MaximumTrivialSize                 = 10;
-    public static int     MaximumInlineLevel                 = 30;
-    public static int     MaximumDesiredSize                 = 3000;
-    public static int     MaximumRecursiveInlining           = 1;
-    public static int     SmallCompiledCodeSize              = 2000;
-    public static boolean LimitInlinedProbability            = ____;
-    // WeightBasedInliningPolicy (0)
-    public static boolean ParseBeforeInlining                = ____;
-    public static float   InliningSizePenaltyExp             = 20;
-    public static float   MaximumInlineWeight                = 1.25f;
-    public static float   InliningSizePenalty                = 1;
-    // StaticSizeBasedInliningPolicy (1), MinimumCodeSizeBasedInlining (2),
-    // DynamicSizeBasedInliningPolicy (3)
-    public static int     MaximumInlineSize                  = 35;
-    // GreedySizeBasedInlining (4)
-    public static int     MaximumGreedyInlineSize            = 100;
-    public static int     InliningBonusPerTransferredValue   = 10;
-    // Common options for inlining policies 1 to 4
-    public static float   NestedInliningSizeRatio            = 1f;
-    public static float   BoostInliningForEscapeAnalysis     = 2f;
-    public static float   ProbabilityCapForInlining          = 1f;
-
-    // escape analysis settings
-    public static boolean PartialEscapeAnalysis              = true;
-
-    public static double TailDuplicationProbability          = 0.5;
-    public static int    TailDuplicationTrivialSize          = 1;
-
-    // absolute probability analysis
-    public static boolean ProbabilityAnalysis                = true;
-    public static int     LoopFrequencyPropagationPolicy     = -2;
-
-    // profiling information
-    public static int     DeoptsToDisableOptimisticOptimization = 40;
-    public static boolean PrintDisabledOptimisticOptimizations = true;
-    public static int     MatureExecutionsBranch             = 1;
-    public static int     MatureExecutionsPerSwitchCase      = 1;
-    public static int     MatureExecutionsTypeProfile        = 1;
-
-    // comilation queue
-    public static int     TimedBootstrap                     = -1;
-    public static boolean PriorityCompileQueue               = true;
-    public static int     SlowQueueCutoff                    = 100000;
-    public static boolean SlowCompileThreads                 = ____;
-    public static boolean DynamicCompilePriority             = ____;
-
-    // graph caching
-    public static boolean CacheGraphs                        = true;
-    public static int     GraphCacheSize                     = 1000;
-    public static boolean PrintGraphCache                    = ____;
-
-    //rematerialize settings
-    public static float   MinimumUsageProbability            = 0.95f;
-
-    //loop transform settings TODO (gd) tune
-    public static boolean LoopPeeling                        = true;
-    public static boolean ReassociateInvariants              = true;
-    public static boolean FullUnroll                         = true;
-    public static boolean LoopUnswitch                       = true;
-    public static int     FullUnrollMaxNodes                 = 150;
-    public static int     ExactFullUnrollMaxNodes            = 600;
-    public static float   MinimumPeelProbability             = 0.35f;
-    public static int     LoopMaxUnswitch                    = 3;
-    public static int     LoopUnswitchMaxIncrease            = 50;
-    public static int     LoopUnswitchUncertaintyBoost       = 5;
-
-    // debugging settings
-    public static int     MethodEndBreakpointGuards          = 0;
-    public static boolean ZapStackOnMethodEntry              = ____;
-    public static boolean DeoptALot                          = ____;
-    public static boolean VerifyPhases                       = true;
-    public static boolean CreateDeoptInfo                    = ____;
-
-    public static String  PrintFilter                        = null;
-
-    // printing settings
-    public static boolean PrintLIR                           = ____;
-    public static boolean PrintCFGToFile                     = ____;
-
-    // Debug settings:
-    public static boolean Debug                              = true;
-    public static boolean PerThreadDebugValues               = ____;
-    public static boolean SummarizeDebugValues               = ____;
-    public static boolean SummarizePerPhase                  = ____;
-    public static String Dump                                = null;
-    public static String Meter                               = null;
-    public static String Time                                = null;
-    public static String Log                                 = null;
-    public static String LogFile                             = null;
-    public static String MethodFilter                        = null;
-    public static boolean DumpOnError                        = ____;
-
-    // Ideal graph visualizer output settings
-    public static boolean PrintBinaryGraphs                  = ____;
-    public static boolean PrintCFG                           = true;
-    public static boolean PrintIdealGraphFile                = ____;
-    public static String  PrintIdealGraphAddress             = "127.0.0.1";
-    public static int     PrintIdealGraphPort                = 4444;
-    public static int     PrintBinaryGraphPort               = 4445;
-
-    // Other printing settings
-    public static boolean PrintQueue                         = ____;
-    public static boolean PrintCompilation                   = ____;
-    public static boolean PrintProfilingInformation          = ____;
-    public static boolean PrintXirTemplates                  = ____;
-    public static boolean PrintIRWithLIR                     = ____;
-    public static boolean PrintAssembly                      = ____;
-    public static boolean PrintCodeBytes                     = ____;
-    public static int     PrintAssemblyBytesPerLine          = 16;
-    public static boolean PrintBailout                       = ____;
-    public static int     TraceLinearScanLevel               = 0;
-    public static boolean TraceRegisterAllocation            = false;
-    public static int     TraceLIRGeneratorLevel             = 0;
-    public static boolean TraceEscapeAnalysis                = ____;
-    public static int     TraceBytecodeParserLevel           = 0;
-    public static boolean PrintBailouts                      = true;
-    public static boolean ExitVMOnBailout                    = ____;
-    public static boolean ExitVMOnException                  = true;
-
-    // state merging settings
-    public static boolean AssumeVerifiedBytecode             = true;
-
-    // Code generator settings
-    public static boolean CheckCastElimination               = true;
-    public static boolean CullFrameStates                    = ____;
-    public static boolean UseProfilingInformation            = true;
-           static boolean RemoveNeverExecutedCode            = true;
-           static boolean UseExceptionProbability            = true;
-    public static boolean AllowExplicitExceptionChecks       = true;
-    public static boolean OmitHotExceptionStacktrace         = ____;
-    public static boolean GenSafepoints                      = true;
-    public static boolean GenLoopSafepoints                  = true;
-           static boolean UseTypeCheckHints                  = true;
-    public static boolean InlineVTableStubs                  = true;
-    public static boolean AlwaysInlineVTableStubs            = ____;
-
-    public static boolean GenAssertionCode                   = ____;
-    public static boolean AlignCallsForPatching              = true;
-    public static boolean ResolveClassBeforeStaticInvoke     = true;
-
-    // Translating tableswitch instructions
-    public static int     SequentialSwitchLimit              = 4;
-    public static int     RangeTestsSwitchDensity            = 5;
-    public static double  MinTableSwitchDensity              = 0.5;
-
-    public static boolean DetailedAsserts                    = ____;
-
-    // Runtime settings
-    public static int     ReadPrefetchInstr                  = 0;
-    public static int     StackShadowPages                   = 2;
-
-    // Assembler settings
-    public static boolean CommentedAssembly                  = ____;
-    public static boolean PrintLIRWithAssembly               = ____;
-
-    public static boolean SupportJsrBytecodes                = true;
-
-    public static boolean OptAssumptions                     = true;
-    public static boolean OptReadElimination                 = true;
-    public static boolean OptGVN                             = true;
-    public static boolean OptCanonicalizer                   = true;
-    public static boolean ScheduleOutOfLoops                 = true;
-    public static boolean OptReorderLoops                    = true;
-    public static boolean OptEliminateGuards                 = true;
-    public static boolean OptImplicitNullChecks              = true;
-    public static boolean OptLivenessAnalysis                = true;
-    public static boolean OptLoopTransform                   = true;
-    public static boolean OptSafepointElimination            = true;
-    public static boolean FloatingReads                      = true;
-    public static boolean OptTailDuplication                 = true;
-
-    /**
-     * Prints all the available GraalOptions.
-     */
-    public static boolean PrintFlags                           = false;
-
-    /**
-     * Counts the various paths taken through snippets.
-     */
-    public static boolean SnippetCounters = false;
-
-    /**
-     * If the probability that a checkcast will hit one the profiled types (up to {@link #CheckcastMaxHints})
-     * is below this value, the checkcast will be compiled without hints.
-     */
-    public static double CheckcastMinHintHitProbability = 0.5;
-
-    /**
-     * The maximum number of hint types that will be used when compiling a checkcast for which
-     * profiling information is available. Note that {@link #CheckcastMinHintHitProbability}
-     * also influences whether hints are used.
-     */
-    public static int CheckcastMaxHints = 2;
-
-    /**
-     * @see #CheckcastMinHintHitProbability
-     */
-    public static double InstanceOfMinHintHitProbability = 0.5;
-
-    /**
-     * @see #CheckcastMaxHints
-     */
-    public static int InstanceOfMaxHints = 1;
-
-    static {
-        // turn detailed assertions on when the general assertions are on (misusing the assert keyword for this)
-        assert (DetailedAsserts = true) == true;
-        assert (CommentedAssembly = true) == true;
-    }
-}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/OptimisticOptimizations.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-/*
- * Copyright (c) 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 com.oracle.graal.compiler;
-
-import java.util.*;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.debug.*;
-
-
-
-public final class OptimisticOptimizations {
-    public static final OptimisticOptimizations ALL = new OptimisticOptimizations(EnumSet.allOf(Optimization.class));
-    public static final OptimisticOptimizations NONE = new OptimisticOptimizations(EnumSet.noneOf(Optimization.class));
-    private static final DebugMetric disabledOptimisticOptsMetric = Debug.metric("DisabledOptimisticOpts");
-
-    private static enum Optimization {
-        RemoveNeverExecutedCode,
-        UseTypeCheckedInlining,
-        UseTypeCheckHints,
-        UseExceptionProbability
-    }
-
-    private final Set<Optimization> enabledOpts;
-
-    public OptimisticOptimizations(ResolvedJavaMethod method) {
-        this.enabledOpts = EnumSet.noneOf(Optimization.class);
-
-        ProfilingInfo profilingInfo = method.profilingInfo();
-        if (checkDeoptimizations(profilingInfo, DeoptimizationReason.UnreachedCode)) {
-            enabledOpts.add(Optimization.RemoveNeverExecutedCode);
-        }
-        if (checkDeoptimizations(profilingInfo, DeoptimizationReason.TypeCheckedInliningViolated)) {
-            enabledOpts.add(Optimization.UseTypeCheckedInlining);
-        }
-        if (checkDeoptimizations(profilingInfo, DeoptimizationReason.OptimizedTypeCheckViolated)) {
-            enabledOpts.add(Optimization.UseTypeCheckHints);
-        }
-        if (checkDeoptimizations(profilingInfo, DeoptimizationReason.NotCompiledExceptionHandler)) {
-            enabledOpts.add(Optimization.UseExceptionProbability);
-        }
-    }
-
-    private OptimisticOptimizations(Set<Optimization> enabledOpts) {
-        this.enabledOpts = enabledOpts;
-    }
-
-    public void log(JavaMethod method) {
-        for (Optimization opt: Optimization.values()) {
-            if (!enabledOpts.contains(opt)) {
-                if (GraalOptions.PrintDisabledOptimisticOptimizations) {
-                    TTY.println("WARN: deactivated optimistic optimization %s for %s", opt.name(), MetaUtil.format("%H.%n(%p)", method));
-                }
-                disabledOptimisticOptsMetric.increment();
-            }
-        }
-    }
-
-    public boolean removeNeverExecutedCode() {
-        return GraalOptions.RemoveNeverExecutedCode && enabledOpts.contains(Optimization.RemoveNeverExecutedCode);
-    }
-
-    public boolean useTypeCheckHints() {
-        return GraalOptions.UseTypeCheckHints && enabledOpts.contains(Optimization.UseTypeCheckHints);
-    }
-
-    public boolean inlineMonomorphicCalls() {
-        return GraalOptions.InlineMonomorphicCalls && enabledOpts.contains(Optimization.UseTypeCheckedInlining);
-    }
-
-    public boolean inlinePolymorphicCalls() {
-        return GraalOptions.InlinePolymorphicCalls && enabledOpts.contains(Optimization.UseTypeCheckedInlining);
-    }
-
-    public boolean inlineMegamorphicCalls() {
-        return GraalOptions.InlineMegamorphicCalls && enabledOpts.contains(Optimization.UseTypeCheckedInlining);
-    }
-
-    public boolean useExceptionProbability() {
-        return GraalOptions.UseExceptionProbability && enabledOpts.contains(Optimization.UseExceptionProbability);
-    }
-
-    public boolean lessOptimisticThan(OptimisticOptimizations other) {
-        for (Optimization opt: Optimization.values()) {
-            if (!enabledOpts.contains(opt) && other.enabledOpts.contains(opt)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private static boolean checkDeoptimizations(ProfilingInfo profilingInfo, DeoptimizationReason reason) {
-        return profilingInfo.getDeoptimizationCount(reason) < GraalOptions.DeoptsToDisableOptimisticOptimization;
-    }
-}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/graph/MergeableState.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.graph;
-
-import java.util.*;
-
-import com.oracle.graal.nodes.*;
-
-public interface MergeableState <T> {
-    T clone();
-    boolean merge(MergeNode merge, List<T> withStates);
-    void loopBegin(LoopBeginNode loopBegin);
-    void loopEnds(LoopBeginNode loopBegin, List<T> loopEndStates);
-    void afterSplit(FixedNode node);
-}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/graph/PostOrderNodeIterator.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,234 +0,0 @@
-/*
- * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.graph;
-
-import java.util.*;
-
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-
-/**
- * A PostOrderNodeIterator iterates the fixed nodes of the graph in post order starting from a specified fixed node.<br>
- * For this iterator the CFG is defined by the classical CFG nodes ({@link ControlSplitNode}, {@link MergeNode}...) and the {@link FixedWithNextNode#next() next} pointers
- * of {@link FixedWithNextNode}.<br>
- * While iterating it maintains a user-defined state by calling the methods available in {@link MergeableState}.
- *
- * @param <T> the type of {@link MergeableState} handled by this PostOrderNodeIterator
- */
-public abstract class PostOrderNodeIterator<T extends MergeableState<T>> {
-
-    private final NodeBitMap visitedEnds;
-    private final Deque<FixedNode> nodeQueue;
-    private final IdentityHashMap<FixedNode, T> nodeStates;
-    private final FixedNode start;
-
-    protected T state;
-
-    public PostOrderNodeIterator(FixedNode start, T initialState) {
-        visitedEnds = start.graph().createNodeBitMap();
-        nodeQueue = new ArrayDeque<>();
-        nodeStates = new IdentityHashMap<>();
-        this.start = start;
-        this.state = initialState;
-    }
-
-    public void apply() {
-        FixedNode current = start;
-
-        do {
-            if (current instanceof InvokeWithExceptionNode) {
-                invoke((Invoke) current);
-                queueSuccessors(current, null);
-                current = nextQueuedNode();
-            } else if (current instanceof LoopBeginNode) {
-                state.loopBegin((LoopBeginNode) current);
-                nodeStates.put(current, state);
-                state = state.clone();
-                loopBegin((LoopBeginNode) current);
-                current = ((LoopBeginNode) current).next();
-                assert current != null;
-            } else if (current instanceof LoopEndNode) {
-                loopEnd((LoopEndNode) current);
-                finishLoopEnds((LoopEndNode) current);
-                current = nextQueuedNode();
-            } else if (current instanceof MergeNode) {
-                merge((MergeNode) current);
-                current = ((MergeNode) current).next();
-                assert current != null;
-            } else if (current instanceof FixedWithNextNode) {
-                FixedNode next = ((FixedWithNextNode) current).next();
-                assert next != null : current;
-                node(current);
-                current = next;
-            } else if (current instanceof EndNode) {
-                end((EndNode) current);
-                queueMerge((EndNode) current);
-                current = nextQueuedNode();
-            } else if (current instanceof DeoptimizeNode) {
-                deoptimize((DeoptimizeNode) current);
-                current = nextQueuedNode();
-            } else if (current instanceof ReturnNode) {
-                returnNode((ReturnNode) current);
-                current = nextQueuedNode();
-            } else if (current instanceof UnwindNode) {
-                unwind((UnwindNode) current);
-                current = nextQueuedNode();
-            } else if (current instanceof ControlSplitNode) {
-                Set<Node> successors = controlSplit((ControlSplitNode) current);
-                queueSuccessors(current, successors);
-                current = nextQueuedNode();
-            } else {
-                assert false : current;
-            }
-        } while(current != null);
-    }
-
-    private void queueSuccessors(FixedNode x, Set<Node> successors) {
-        nodeStates.put(x, state);
-        if (successors != null) {
-            for (Node node : successors) {
-                if (node != null) {
-                    nodeStates.put((FixedNode) node.predecessor(), state);
-                    nodeQueue.addFirst((FixedNode) node);
-                }
-            }
-        } else {
-            for (Node node : x.successors()) {
-                if (node != null) {
-                    nodeQueue.addFirst((FixedNode) node);
-                }
-            }
-        }
-    }
-
-    private FixedNode nextQueuedNode() {
-        int maxIterations = nodeQueue.size();
-        while (maxIterations-- > 0) {
-            FixedNode node = nodeQueue.removeFirst();
-            if (node instanceof MergeNode) {
-                MergeNode merge = (MergeNode) node;
-                state = nodeStates.get(merge.forwardEndAt(0)).clone();
-                ArrayList<T> states = new ArrayList<>(merge.forwardEndCount() - 1);
-                for (int i = 1; i < merge.forwardEndCount(); i++) {
-                    T other = nodeStates.get(merge.forwardEndAt(i));
-                    assert other != null;
-                    states.add(other);
-                }
-                boolean ready = state.merge(merge, states);
-                if (ready) {
-                    return merge;
-                } else {
-                    nodeQueue.addLast(merge);
-                }
-            } else {
-                assert node.predecessor() != null;
-                state = nodeStates.get(node.predecessor()).clone();
-                state.afterSplit(node);
-                return node;
-            }
-        }
-        return null;
-    }
-
-    private void finishLoopEnds(LoopEndNode end) {
-        assert !visitedEnds.isMarked(end);
-        assert !nodeStates.containsKey(end);
-        nodeStates.put(end, state);
-        visitedEnds.mark(end);
-        LoopBeginNode begin = end.loopBegin();
-        boolean endsVisited = true;
-        for (LoopEndNode le : begin.loopEnds()) {
-            if (!visitedEnds.isMarked(le)) {
-                endsVisited = false;
-                break;
-            }
-        }
-        if (endsVisited) {
-            ArrayList<T> states = new ArrayList<>(begin.loopEnds().count());
-            for (LoopEndNode le : begin.orderedLoopEnds()) {
-                states.add(nodeStates.get(le));
-            }
-            T loopBeginState = nodeStates.get(begin);
-            if (loopBeginState != null) {
-                loopBeginState.loopEnds(begin, states);
-            }
-        }
-    }
-
-    private void queueMerge(EndNode end) {
-        assert !visitedEnds.isMarked(end);
-        assert !nodeStates.containsKey(end);
-        nodeStates.put(end, state);
-        visitedEnds.mark(end);
-        MergeNode merge = end.merge();
-        boolean endsVisited = true;
-        for (int i = 0; i < merge.forwardEndCount(); i++) {
-            if (!visitedEnds.isMarked(merge.forwardEndAt(i))) {
-                endsVisited = false;
-                break;
-            }
-        }
-        if (endsVisited) {
-            nodeQueue.add(merge);
-        }
-    }
-
-    protected abstract void node(FixedNode node);
-
-    protected void end(EndNode endNode) {
-        node(endNode);
-    }
-
-    protected void merge(MergeNode merge) {
-        node(merge);
-    }
-
-    protected void loopBegin(LoopBeginNode loopBegin) {
-        node(loopBegin);
-    }
-
-    protected void loopEnd(LoopEndNode loopEnd) {
-        node(loopEnd);
-    }
-
-    protected void deoptimize(DeoptimizeNode deoptimize) {
-        node(deoptimize);
-    }
-
-    protected Set<Node> controlSplit(ControlSplitNode controlSplit) {
-        node(controlSplit);
-        return null;
-    }
-
-    protected void returnNode(ReturnNode returnNode) {
-        node(returnNode);
-    }
-
-    protected void invoke(Invoke invoke) {
-        node(invoke.node());
-    }
-
-    protected void unwind(UnwindNode unwind) {
-        node(unwind);
-    }
-}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/graph/package-info.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/**
- *
- */
-package com.oracle.graal.compiler.graph;
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/package-info.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/**
- * The top-level package in Graal containing options, metrics and timers.
- *
- * Graal is intended to be used with multiple JVM's so makes no use of or reference to classes for a specific JVM.
- */
-package com.oracle.graal.compiler;
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/BoxingEliminationPhase.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,137 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.phases;
-
-import static com.oracle.graal.graph.iterators.NodePredicates.*;
-
-import java.util.*;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.iterators.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.nodes.virtual.*;
-
-public class BoxingEliminationPhase extends Phase {
-
-    private int virtualIds = Integer.MIN_VALUE;
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        if (graph.getNodes(UnboxNode.class).isNotEmpty()) {
-
-            Map<PhiNode, PhiNode> phiReplacements = new HashMap<>();
-            for (UnboxNode unboxNode : graph.getNodes(UnboxNode.class)) {
-                tryEliminate(graph, unboxNode, phiReplacements);
-            }
-
-            new DeadCodeEliminationPhase().apply(graph);
-
-            for (BoxNode boxNode : graph.getNodes(BoxNode.class)) {
-                tryEliminate(boxNode);
-            }
-        }
-    }
-
-    private void tryEliminate(StructuredGraph graph, UnboxNode unboxNode, Map<PhiNode, PhiNode> phiReplacements) {
-        ValueNode unboxedValue = unboxedValue(unboxNode.source(), unboxNode.destinationKind(), phiReplacements);
-        if (unboxedValue != null) {
-            assert unboxedValue.kind() == unboxNode.kind();
-            unboxNode.replaceAtUsages(unboxedValue);
-            graph.removeFixed(unboxNode);
-        }
-    }
-
-    private PhiNode getReplacementPhi(PhiNode phiNode, Kind kind, Map<PhiNode, PhiNode> phiReplacements) {
-        if (!phiReplacements.containsKey(phiNode)) {
-            PhiNode result = null;
-            ObjectStamp stamp = phiNode.objectStamp();
-            if (stamp.nonNull() && stamp.isExactType()) {
-                ResolvedJavaType type = stamp.type();
-                if (type != null && type.toJava() == kind.toBoxedJavaClass()) {
-                    StructuredGraph graph = (StructuredGraph) phiNode.graph();
-                    result = graph.add(new PhiNode(kind, phiNode.merge()));
-                    phiReplacements.put(phiNode, result);
-                    virtualizeUsages(phiNode, result, type);
-                    int i = 0;
-                    for (ValueNode n : phiNode.values()) {
-                        ValueNode unboxedValue = unboxedValue(n, kind, phiReplacements);
-                        if (unboxedValue != null) {
-                            assert unboxedValue.kind() == kind;
-                            result.addInput(unboxedValue);
-                        } else {
-                            UnboxNode unboxNode = graph.add(new UnboxNode(kind, n));
-                            FixedNode pred = phiNode.merge().phiPredecessorAt(i);
-                            graph.addBeforeFixed(pred, unboxNode);
-                            result.addInput(unboxNode);
-                        }
-                        ++i;
-                    }
-                }
-            }
-        }
-        return phiReplacements.get(phiNode);
-    }
-
-    private ValueNode unboxedValue(ValueNode n, Kind kind, Map<PhiNode, PhiNode> phiReplacements) {
-        if (n instanceof BoxNode) {
-            BoxNode boxNode = (BoxNode) n;
-            return boxNode.source();
-        } else if (n instanceof PhiNode) {
-            PhiNode phiNode = (PhiNode) n;
-            return getReplacementPhi(phiNode, kind, phiReplacements);
-        } else {
-            return null;
-        }
-    }
-
-    private void tryEliminate(BoxNode boxNode) {
-
-        assert boxNode.objectStamp().isExactType();
-        virtualizeUsages(boxNode, boxNode.source(), boxNode.objectStamp().type());
-
-        if (boxNode.usages().filter(isNotA(VirtualState.class)).isNotEmpty()) {
-            // Elimination failed, because boxing object escapes.
-            return;
-        }
-
-        FrameState stateAfter = boxNode.stateAfter();
-        boxNode.setStateAfter(null);
-        stateAfter.safeDelete();
-
-        ((StructuredGraph) boxNode.graph()).removeFixed(boxNode);
-    }
-
-    private void virtualizeUsages(ValueNode boxNode, ValueNode replacement, ResolvedJavaType exactType) {
-        ValueNode virtualValueNode = null;
-        VirtualObjectNode virtualObjectNode = null;
-        for (Node n : boxNode.usages().filter(NodePredicates.isA(VirtualState.class)).snapshot()) {
-            if (virtualValueNode == null) {
-                virtualObjectNode = n.graph().unique(new BoxedVirtualObjectNode(virtualIds++, exactType, replacement));
-            }
-            n.replaceFirstInput(boxNode, virtualObjectNode);
-        }
-    }
-}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/CanonicalizerPhase.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,331 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.phases;
-
-import java.util.*;
-import java.util.concurrent.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.Graph.InputChangedListener;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.nodes.util.*;
-
-public class CanonicalizerPhase extends Phase {
-    private static final int MAX_ITERATION_PER_NODE = 10;
-    private static final DebugMetric METRIC_CANONICALIZED_NODES = Debug.metric("CanonicalizedNodes");
-    private static final DebugMetric METRIC_CANONICALIZATION_CONSIDERED_NODES = Debug.metric("CanonicalizationConsideredNodes");
-    private static final DebugMetric METRIC_INFER_STAMP_CALLED = Debug.metric("InferStampCalled");
-    private static final DebugMetric METRIC_STAMP_CHANGED = Debug.metric("StampChanged");
-    private static final DebugMetric METRIC_SIMPLIFICATION_CONSIDERED_NODES = Debug.metric("SimplificationConsideredNodes");
-    public static final DebugMetric METRIC_GLOBAL_VALUE_NUMBERING_HITS = Debug.metric("GlobalValueNumberingHits");
-
-    private final int newNodesMark;
-    private final TargetDescription target;
-    private final Assumptions assumptions;
-    private final MetaAccessProvider runtime;
-    private final IsImmutablePredicate immutabilityPredicate;
-    private final Iterable<Node> initWorkingSet;
-
-    private NodeWorkList workList;
-    private Tool tool;
-    private List<Node> snapshotTemp;
-
-    public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions) {
-        this(target, runtime, assumptions, null, 0, null);
-    }
-
-    /**
-     * @param target
-     * @param runtime
-     * @param assumptions
-     * @param workingSet the initial working set of nodes on which the canonicalizer works, should be an auto-grow node bitmap
-     * @param immutabilityPredicate
-     */
-    public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, Iterable<Node> workingSet, IsImmutablePredicate immutabilityPredicate) {
-        this(target, runtime, assumptions, workingSet, 0, immutabilityPredicate);
-    }
-
-    /**
-     * @param newNodesMark only the {@linkplain Graph#getNewNodes(int) new nodes} specified by
-     *            this mark are processed otherwise all nodes in the graph are processed
-     */
-    public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, int newNodesMark, IsImmutablePredicate immutabilityPredicate) {
-        this(target, runtime, assumptions, null, newNodesMark, immutabilityPredicate);
-    }
-
-    private CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, Iterable<Node> workingSet, int newNodesMark, IsImmutablePredicate immutabilityPredicate) {
-        this.newNodesMark = newNodesMark;
-        this.target = target;
-        this.assumptions = assumptions;
-        this.runtime = runtime;
-        this.immutabilityPredicate = immutabilityPredicate;
-        this.initWorkingSet = workingSet;
-        this.snapshotTemp = new ArrayList<>();
-    }
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        if (initWorkingSet == null) {
-            workList = graph.createNodeWorkList(newNodesMark == 0, MAX_ITERATION_PER_NODE);
-            if (newNodesMark > 0) {
-                workList.addAll(graph.getNewNodes(newNodesMark));
-            }
-        } else {
-            workList = graph.createNodeWorkList(false, MAX_ITERATION_PER_NODE);
-            workList.addAll(initWorkingSet);
-        }
-        tool = new Tool(workList, runtime, target, assumptions, immutabilityPredicate);
-        processWorkSet(graph);
-    }
-
-    public interface IsImmutablePredicate {
-        /**
-         * Determines if a given constant is an object/array whose current
-         * fields/elements will never change.
-         */
-        boolean apply(Constant constant);
-    }
-
-    private void processWorkSet(StructuredGraph graph) {
-        graph.trackInputChange(new InputChangedListener() {
-            @Override
-            public void inputChanged(Node node) {
-                workList.addAgain(node);
-            }
-        });
-
-        for (Node n : workList) {
-            processNode(n, graph);
-        }
-
-        graph.stopTrackingInputChange();
-    }
-
-    private void processNode(Node node, StructuredGraph graph) {
-        if (node.isAlive()) {
-            METRIC_PROCESSED_NODES.increment();
-
-            if (tryGlobalValueNumbering(node, graph)) {
-                return;
-            }
-            int mark = graph.getMark();
-            if (!tryKillUnused(node)) {
-                node.inputs().filter(GraphUtil.isFloatingNode()).snapshotTo(snapshotTemp);
-                if (!tryCanonicalize(node, graph, tool)) {
-                    tryInferStamp(node, graph);
-                } else {
-                    for (Node in : snapshotTemp) {
-                        if (in.isAlive() && in.usages().isEmpty()) {
-                            GraphUtil.killWithUnusedFloatingInputs(in);
-                        }
-                    }
-                }
-                snapshotTemp.clear();
-            }
-
-            for (Node newNode : graph.getNewNodes(mark)) {
-                workList.add(newNode);
-            }
-        }
-    }
-
-    private static boolean tryKillUnused(Node node) {
-        if (node.isAlive() && GraphUtil.isFloatingNode().apply(node) && node.usages().isEmpty()) {
-            GraphUtil.killWithUnusedFloatingInputs(node);
-            return true;
-        }
-        return false;
-    }
-
-    public static boolean tryGlobalValueNumbering(Node node, StructuredGraph graph) {
-        if (node.getNodeClass().valueNumberable()) {
-            Node newNode = graph.findDuplicate(node);
-            if (newNode != null) {
-                assert !(node instanceof FixedNode || newNode instanceof FixedNode);
-                node.replaceAtUsages(newNode);
-                node.safeDelete();
-                METRIC_GLOBAL_VALUE_NUMBERING_HITS.increment();
-                Debug.log("GVN applied and new node is %1s", newNode);
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public static boolean tryCanonicalize(final Node node, final StructuredGraph graph, final SimplifierTool tool) {
-        if (node instanceof Canonicalizable) {
-            assert !(node instanceof Simplifiable);
-            METRIC_CANONICALIZATION_CONSIDERED_NODES.increment();
-            return Debug.scope("CanonicalizeNode", node, new Callable<Boolean>(){
-                public Boolean call() {
-                    ValueNode canonical = ((Canonicalizable) node).canonical(tool);
-//     cases:                                           original node:
-//                                         |Floating|Fixed-unconnected|Fixed-connected|
-//                                         --------------------------------------------
-//                                     null|   1    |        X        |       3       |
-//                                         --------------------------------------------
-//                                 Floating|   2    |        X        |       4       |
-//       canonical node:                   --------------------------------------------
-//                        Fixed-unconnected|   X    |        X        |       5       |
-//                                         --------------------------------------------
-//                          Fixed-connected|   2    |        X        |       6       |
-//                                         --------------------------------------------
-//       X: must not happen (checked with assertions)
-                    if (canonical == node) {
-                        Debug.log("Canonicalizer: work on %s", node);
-                        return false;
-                    } else {
-                        Debug.log("Canonicalizer: replacing %s with %s", node, canonical);
-                        METRIC_CANONICALIZED_NODES.increment();
-                        if (node instanceof FloatingNode) {
-                            if (canonical == null) {
-                                // case 1
-                                graph.removeFloating((FloatingNode) node);
-                            } else {
-                                // case 2
-                                assert !(canonical instanceof FixedNode) || (canonical.predecessor() != null || canonical instanceof StartNode) : node + " -> " + canonical +
-                                                " : replacement should be floating or fixed and connected";
-                                graph.replaceFloating((FloatingNode) node, canonical);
-                            }
-                        } else {
-                            assert node instanceof FixedWithNextNode && node.predecessor() != null : node + " -> " + canonical + " : node should be fixed & connected (" + node.predecessor() + ")";
-                            if (canonical == null) {
-                                // case 3
-                                graph.removeFixed((FixedWithNextNode) node);
-                            } else if (canonical instanceof FloatingNode) {
-                                // case 4
-                                graph.replaceFixedWithFloating((FixedWithNextNode) node, (FloatingNode) canonical);
-                            } else {
-                                assert canonical instanceof FixedNode;
-                                if (canonical.predecessor() == null) {
-                                    assert !canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " shouldn't have successors";
-                                    // case 5
-                                    graph.replaceFixedWithFixed((FixedWithNextNode) node, (FixedWithNextNode) canonical);
-                                } else {
-                                    assert canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " should have successors";
-                                    // case 6
-                                    node.replaceAtUsages(canonical);
-                                    graph.removeFixed((FixedWithNextNode) node);
-                                }
-                            }
-                        }
-                        return true;
-                    }
-                }
-            });
-        } else if (node instanceof Simplifiable) {
-            Debug.log("Canonicalizer: simplifying %s", node);
-            METRIC_SIMPLIFICATION_CONSIDERED_NODES.increment();
-            Debug.scope("SimplifyNode", node, new Runnable() {
-                public void run() {
-                    ((Simplifiable) node).simplify(tool);
-                }
-            });
-        }
-        return node.isDeleted();
-    }
-
-    /**
-     * Calls {@link ValueNode#inferStamp()} on the node and, if it returns true (which means that the stamp has
-     * changed), re-queues the node's usages . If the stamp has changed then this method also checks if the stamp
-     * now describes a constant integer value, in which case the node is replaced with a constant.
-     */
-    private void tryInferStamp(Node node, StructuredGraph graph) {
-        if (node.isAlive() && node instanceof ValueNode) {
-            ValueNode valueNode = (ValueNode) node;
-            METRIC_INFER_STAMP_CALLED.increment();
-            if (valueNode.inferStamp()) {
-                METRIC_STAMP_CHANGED.increment();
-                if (valueNode.stamp() instanceof IntegerStamp && valueNode.integerStamp().lowerBound() == valueNode.integerStamp().upperBound()) {
-                    ValueNode replacement = ConstantNode.forIntegerKind(valueNode.kind(), valueNode.integerStamp().lowerBound(), graph);
-                    Debug.log("Canonicalizer: replacing %s with %s (inferStamp)", valueNode, replacement);
-                    valueNode.replaceAtUsages(replacement);
-                } else {
-                    for (Node usage : valueNode.usages()) {
-                        workList.addAgain(usage);
-                    }
-                }
-            }
-        }
-    }
-
-    private static final class Tool implements SimplifierTool {
-
-        private final NodeWorkList nodeWorkSet;
-        private final MetaAccessProvider runtime;
-        private final TargetDescription target;
-        private final Assumptions assumptions;
-        private final IsImmutablePredicate immutabilityPredicate;
-
-        public Tool(NodeWorkList nodeWorkSet, MetaAccessProvider runtime, TargetDescription target, Assumptions assumptions, IsImmutablePredicate immutabilityPredicate) {
-            this.nodeWorkSet = nodeWorkSet;
-            this.runtime = runtime;
-            this.target = target;
-            this.assumptions = assumptions;
-            this.immutabilityPredicate = immutabilityPredicate;
-        }
-
-        @Override
-        public void deleteBranch(FixedNode branch) {
-            branch.predecessor().replaceFirstSuccessor(branch, null);
-            GraphUtil.killCFG(branch);
-        }
-
-        /**
-         * @return the current target or {@code null} if no target is available in the current context.
-         */
-        @Override
-        public TargetDescription target() {
-            return target;
-        }
-
-        /**
-         * @return an object that can be used for recording assumptions or {@code null} if assumptions are not allowed in the current context.
-         */
-        @Override
-        public Assumptions assumptions() {
-            return assumptions;
-        }
-
-        @Override
-        public MetaAccessProvider runtime() {
-            return runtime;
-        }
-
-        @Override
-        public void addToWorkList(Node node) {
-            nodeWorkSet.add(node);
-        }
-
-        @Override
-        public boolean isImmutable(Constant objectConstant) {
-            return immutabilityPredicate != null && immutabilityPredicate.apply(objectConstant);
-        }
-    }
-}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/CheckCastEliminationPhase.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,383 +0,0 @@
-/*
- * Copyright (c) 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 com.oracle.graal.compiler.phases;
-
-import java.util.*;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.graph.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.nodes.util.*;
-
-public class CheckCastEliminationPhase extends Phase {
-
-    private static final DebugMetric metricInstanceOfRegistered = Debug.metric("InstanceOfRegistered");
-    private static final DebugMetric metricNullCheckRegistered = Debug.metric("NullCheckRegistered");
-    private static final DebugMetric metricCheckCastRemoved = Debug.metric("CheckCastRemoved");
-    private static final DebugMetric metricInstanceOfRemoved = Debug.metric("InstanceOfRemoved");
-    private static final DebugMetric metricNullCheckRemoved = Debug.metric("NullCheckRemoved");
-    private static final DebugMetric metricNullCheckGuardRemoved = Debug.metric("NullCheckGuardRemoved");
-    private static final DebugMetric metricGuardsReplaced = Debug.metric("GuardsReplaced");
-
-    private StructuredGraph graph;
-
-    @Override
-    protected void run(StructuredGraph inputGraph) {
-        graph = inputGraph;
-        new EliminateCheckCasts(graph.start(), new State()).apply();
-    }
-
-    public static class State implements MergeableState<State> {
-
-        private IdentityHashMap<ValueNode, ResolvedJavaType> knownTypes;
-        private HashSet<ValueNode> knownNotNull;
-        private HashSet<ValueNode> knownNull;
-        private IdentityHashMap<BooleanNode, ValueNode> trueConditions;
-        private IdentityHashMap<BooleanNode, ValueNode> falseConditions;
-
-        public State() {
-            this.knownTypes = new IdentityHashMap<>();
-            this.knownNotNull = new HashSet<>();
-            this.knownNull = new HashSet<>();
-            this.trueConditions = new IdentityHashMap<>();
-            this.falseConditions = new IdentityHashMap<>();
-        }
-
-        public State(State other) {
-            this.knownTypes = new IdentityHashMap<>(other.knownTypes);
-            this.knownNotNull = new HashSet<>(other.knownNotNull);
-            this.knownNull = new HashSet<>(other.knownNull);
-            this.trueConditions = new IdentityHashMap<>(other.trueConditions);
-            this.falseConditions = new IdentityHashMap<>(other.falseConditions);
-        }
-
-        @Override
-        public boolean merge(MergeNode merge, List<State> withStates) {
-            IdentityHashMap<ValueNode, ResolvedJavaType> newKnownTypes = new IdentityHashMap<>();
-            HashSet<ValueNode> newKnownNotNull = new HashSet<>();
-            HashSet<ValueNode> newKnownNull = new HashSet<>();
-            IdentityHashMap<BooleanNode, ValueNode> newTrueConditions = new IdentityHashMap<>();
-            IdentityHashMap<BooleanNode, ValueNode> newFalseConditions = new IdentityHashMap<>();
-
-            for (Map.Entry<ValueNode, ResolvedJavaType> entry : knownTypes.entrySet()) {
-                ValueNode node = entry.getKey();
-                ResolvedJavaType type = entry.getValue();
-
-                for (State other : withStates) {
-                    ResolvedJavaType otherType = other.getNodeType(node);
-                    type = widen(type, otherType);
-                    if (type == null) {
-                        break;
-                    }
-                }
-                if (type == null && type != node.objectStamp().type()) {
-                    newKnownTypes.put(node, type);
-                }
-            }
-            for (ValueNode node : knownNotNull) {
-                boolean notNull = true;
-                for (State other : withStates) {
-                    if (!other.knownNotNull.contains(node)) {
-                        notNull = false;
-                        break;
-                    }
-                }
-                if (notNull) {
-                    newKnownNotNull.add(node);
-                }
-            }
-            for (ValueNode node : knownNull) {
-                boolean nul = true;
-                for (State other : withStates) {
-                    if (!other.knownNull.contains(node)) {
-                        nul = false;
-                        break;
-                    }
-                }
-                if (nul) {
-                    newKnownNull.add(node);
-                }
-            }
-            for (Map.Entry<BooleanNode, ValueNode> entry : trueConditions.entrySet()) {
-                BooleanNode check = entry.getKey();
-                ValueNode guard = entry.getValue();
-
-                for (State other : withStates) {
-                    ValueNode otherGuard = other.trueConditions.get(check);
-                    if (otherGuard == null) {
-                        guard = null;
-                        break;
-                    }
-                    if (otherGuard != guard) {
-                        guard = merge;
-                    }
-                }
-                if (guard != null) {
-                    newTrueConditions.put(check, guard);
-                }
-            }
-            for (Map.Entry<BooleanNode, ValueNode> entry : falseConditions.entrySet()) {
-                BooleanNode check = entry.getKey();
-                ValueNode guard = entry.getValue();
-
-                for (State other : withStates) {
-                    ValueNode otherGuard = other.falseConditions.get(check);
-                    if (otherGuard == null) {
-                        guard = null;
-                        break;
-                    }
-                    if (otherGuard != guard) {
-                        guard = merge;
-                    }
-                }
-                if (guard != null) {
-                    newFalseConditions.put(check, guard);
-                }
-            }
-
-            /*
-            // this piece of code handles phis (merges the types and knownNull/knownNotNull of the values)
-            if (!(merge instanceof LoopBeginNode)) {
-                for (PhiNode phi : merge.phis()) {
-                    if (phi.type() == PhiType.Value && phi.kind() == Kind.Object) {
-                        ValueNode firstValue = phi.valueAt(0);
-                        ResolvedJavaType type = getNodeType(firstValue);
-                        boolean notNull = knownNotNull.contains(firstValue);
-                        boolean nul = knownNull.contains(firstValue);
-
-                        for (int i = 0; i < withStates.size(); i++) {
-                            State otherState = withStates.get(i);
-                            ValueNode value = phi.valueAt(i + 1);
-                            ResolvedJavaType otherType = otherState.getNodeType(value);
-                            type = widen(type, otherType);
-                            notNull &= otherState.knownNotNull.contains(value);
-                            nul &= otherState.knownNull.contains(value);
-                        }
-                        if (type == null && type != phi.declaredType()) {
-                            newKnownTypes.put(phi, type);
-                        }
-                        if (notNull) {
-                            newKnownNotNull.add(phi);
-                        }
-                        if (nul) {
-                            newKnownNull.add(phi);
-                        }
-                    }
-                }
-            }
-            */
-            this.knownTypes = newKnownTypes;
-            this.knownNotNull = newKnownNotNull;
-            this.knownNull = newKnownNull;
-            this.trueConditions = newTrueConditions;
-            this.falseConditions = newFalseConditions;
-            return true;
-        }
-
-        public ResolvedJavaType getNodeType(ValueNode node) {
-            ResolvedJavaType result = knownTypes.get(node);
-            return result == null ? node.objectStamp().type() : result;
-        }
-
-        @Override
-        public void loopBegin(LoopBeginNode loopBegin) {
-        }
-
-        @Override
-        public void loopEnds(LoopBeginNode loopBegin, List<State> loopEndStates) {
-        }
-
-        @Override
-        public void afterSplit(FixedNode node) {
-        }
-
-        @Override
-        public State clone() {
-            return new State(this);
-        }
-    }
-
-    public static ResolvedJavaType widen(ResolvedJavaType a, ResolvedJavaType b) {
-        if (a == null || b == null) {
-            return null;
-        } else if (a == b) {
-            return a;
-        } else {
-            return a.leastCommonAncestor(b);
-        }
-    }
-
-    public static ResolvedJavaType tighten(ResolvedJavaType a, ResolvedJavaType b) {
-        if (a == null) {
-            return b;
-        } else if (b == null) {
-            return a;
-        } else if (a == b) {
-            return a;
-        } else if (a.isSubtypeOf(b)) {
-            return a;
-        } else if (b.isSubtypeOf(a)) {
-            return b;
-        } else {
-            return a;
-        }
-    }
-
-    public class EliminateCheckCasts extends PostOrderNodeIterator<State> {
-        private BeginNode lastBegin = null;
-
-        public EliminateCheckCasts(FixedNode start, State initialState) {
-            super(start, initialState);
-        }
-
-        @Override
-        protected void node(FixedNode node) {
-            if (node instanceof BeginNode) {
-                BeginNode begin = (BeginNode) node;
-                lastBegin = begin;
-                Node pred = node.predecessor();
-                if (pred != null && pred instanceof IfNode) {
-                    IfNode ifNode = (IfNode) pred;
-                    if (!(ifNode.compare() instanceof ConstantNode)) {
-                        boolean isTrue = (node == ifNode.trueSuccessor());
-                        if (isTrue) {
-                            state.trueConditions.put(ifNode.compare(), begin);
-                        } else {
-                            state.falseConditions.put(ifNode.compare(), begin);
-                        }
-                    }
-                    if (ifNode.compare() instanceof InstanceOfNode) {
-                        InstanceOfNode instanceOf = (InstanceOfNode) ifNode.compare();
-                        if ((node == ifNode.trueSuccessor())) {
-                            ValueNode object = instanceOf.object();
-                            state.knownNotNull.add(object);
-                            state.knownTypes.put(object, tighten(instanceOf.targetClass(), state.getNodeType(object)));
-                            metricInstanceOfRegistered.increment();
-                        }
-                    } else if (ifNode.compare() instanceof IsNullNode) {
-                        IsNullNode nullCheck = (IsNullNode) ifNode.compare();
-                        boolean isNull = (node == ifNode.trueSuccessor());
-                        if (isNull) {
-                            state.knownNull.add(nullCheck.object());
-                        } else {
-                            state.knownNotNull.add(nullCheck.object());
-                        }
-                        metricNullCheckRegistered.increment();
-                    }
-                }
-                for (GuardNode guard : begin.guards().snapshot()) {
-                    BooleanNode condition = guard.condition();
-                    ValueNode existingGuards = guard.negated() ? state.falseConditions.get(condition) : state.trueConditions.get(condition);
-                    if (existingGuards != null) {
-                        guard.replaceAtUsages(existingGuards);
-                        GraphUtil.killWithUnusedFloatingInputs(guard);
-                        metricGuardsReplaced.increment();
-                    } else {
-                        boolean removeCheck = false;
-                        if (condition instanceof IsNullNode) {
-                            IsNullNode isNull = (IsNullNode) condition;
-                            if (guard.negated() && state.knownNotNull.contains(isNull.object())) {
-                                removeCheck = true;
-                            } else if (!guard.negated() && state.knownNull.contains(isNull.object())) {
-                                removeCheck = true;
-                            }
-                            if (removeCheck) {
-                                metricNullCheckGuardRemoved.increment();
-                            }
-                        }
-                        if (removeCheck) {
-                            guard.replaceAtUsages(begin);
-                            GraphUtil.killWithUnusedFloatingInputs(guard);
-                        } else {
-                            if (guard.negated()) {
-                                state.falseConditions.put(condition, guard);
-                            } else {
-                                state.trueConditions.put(condition, guard);
-                            }
-                        }
-                    }
-                }
-            } else if (node instanceof CheckCastNode) {
-                CheckCastNode checkCast = (CheckCastNode) node;
-                ResolvedJavaType type = state.getNodeType(checkCast.object());
-                if (checkCast.targetClass() != null && type != null && type.isSubtypeOf(checkCast.targetClass())) {
-                    PiNode piNode;
-                    boolean nonNull = state.knownNotNull.contains(checkCast.object());
-                    piNode = graph.unique(new PiNode(checkCast.object(), lastBegin, nonNull ? StampFactory.declaredNonNull(type) : StampFactory.declared(type)));
-                    checkCast.replaceAtUsages(piNode);
-                    graph.removeFixed(checkCast);
-                    metricCheckCastRemoved.increment();
-                }
-            } else if (node instanceof IfNode) {
-                IfNode ifNode = (IfNode) node;
-                BooleanNode replaceWith = null;
-                BooleanNode compare = ifNode.compare();
-
-                if (state.trueConditions.containsKey(compare)) {
-                    replaceWith = ConstantNode.forBoolean(true, graph);
-                } else if (state.falseConditions.containsKey(compare)) {
-                    replaceWith = ConstantNode.forBoolean(false, graph);
-                } else {
-                    if (compare instanceof InstanceOfNode) {
-                        InstanceOfNode instanceOf = (InstanceOfNode) compare;
-                        ValueNode object = instanceOf.object();
-                        if (state.knownNull.contains(object)) {
-                            replaceWith = ConstantNode.forBoolean(false, graph);
-                        } else if (state.knownNotNull.contains(object)) {
-                            ResolvedJavaType type = state.getNodeType(object);
-                            if (type != null && type.isSubtypeOf(instanceOf.targetClass())) {
-                                replaceWith = ConstantNode.forBoolean(true, graph);
-                            }
-                        }
-                        if (replaceWith != null) {
-                            metricInstanceOfRemoved.increment();
-                        }
-                    } else if (compare instanceof IsNullNode) {
-                        IsNullNode isNull = (IsNullNode) compare;
-                        ValueNode object = isNull.object();
-                        if (state.knownNull.contains(object)) {
-                            replaceWith = ConstantNode.forBoolean(true, graph);
-                        } else if (state.knownNotNull.contains(object)) {
-                            replaceWith = ConstantNode.forBoolean(false, graph);
-                        }
-                        if (replaceWith != null) {
-                            metricNullCheckRemoved.increment();
-                        }
-                    }
-                }
-                if (replaceWith != null) {
-                    ifNode.setCompare(replaceWith);
-                    if (compare.usages().isEmpty()) {
-                        GraphUtil.killWithUnusedFloatingInputs(compare);
-                    }
-                }
-            }
-        }
-    }
-
-}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/ComputeProbabilityPhase.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,372 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.phases;
-
-import java.util.*;
-
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.graph.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.lir.cfg.*;
-import com.oracle.graal.nodes.*;
-
-public class ComputeProbabilityPhase extends Phase {
-    private static final double EPSILON = 1d / Integer.MAX_VALUE;
-
-    /*
-     * The computation of absolute probabilities works in three steps:
-     *
-     * - The first step, "PropagateProbability", traverses the graph in post order (merges after their ends, ...) and keeps track of the "probability state".
-     *   Whenever it encounters a ControlSplit it uses the split's probability information to divide the probability upon the successors.
-     *   Whenever it encounters an Invoke it assumes that the exception edge is unlikely and propagates the whole probability to the normal successor.
-     *   Whenever it encounters a Merge it sums up the probability of all predecessors.
-     *   It also maintains a set of active loops (whose LoopBegin has been visited) and builds def/use information for the second step.
-     *
-     * - The third step propagates the loop frequencies and multiplies each FixedNode's probability with its loop frequency.
-     *
-     *   TODO: add exception probability information to Invokes
-     */
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        new PropagateProbability(graph.start()).apply();
-        Debug.dump(graph, "After PropagateProbability");
-        computeLoopFactors();
-        Debug.dump(graph, "After computeLoopFactors");
-        new PropagateLoopFrequency(graph.start()).apply();
-
-        if (GraalOptions.LoopFrequencyPropagationPolicy < 0) {
-            ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, false, false);
-            BitSet visitedBlocks = new BitSet(cfg.getBlocks().length);
-            for (Loop loop : cfg.getLoops()) {
-                if (loop.parent == null) {
-                    correctLoopFrequencies(loop, 1, visitedBlocks);
-                }
-            }
-        }
-    }
-
-    private void correctLoopFrequencies(Loop loop, double parentFrequency, BitSet visitedBlocks) {
-        LoopBeginNode loopBegin = ((LoopBeginNode) loop.header.getBeginNode());
-        double frequency = parentFrequency * loopBegin.loopFrequency();
-        for (Loop child : loop.children) {
-            correctLoopFrequencies(child, frequency, visitedBlocks);
-        }
-
-        double factor = getCorrectionFactor(loopBegin.probability(), frequency);
-        for (Block block : loop.blocks) {
-            int blockId = block.getId();
-            if (!visitedBlocks.get(blockId)) {
-                visitedBlocks.set(blockId);
-
-                FixedNode node = block.getBeginNode();
-                while (node != block.getEndNode()) {
-                    node.setProbability(node.probability() * factor);
-                    node = ((FixedWithNextNode) node).next();
-                }
-                node.setProbability(node.probability() * factor);
-            }
-        }
-    }
-
-    private static double getCorrectionFactor(double probability, double frequency) {
-        switch (GraalOptions.LoopFrequencyPropagationPolicy) {
-            case -1:
-                return 1 / frequency;
-            case -2:
-                return (1 / frequency) * (Math.log(Math.E + frequency) - 1);
-            case -3:
-                double originalProbability = probability / frequency;
-                assert isRelativeProbability(originalProbability);
-                return (1 / frequency) * Math.max(1, Math.pow(originalProbability, 1.5) * Math.log10(frequency));
-            default:
-                throw GraalInternalError.shouldNotReachHere();
-        }
-    }
-
-    private void computeLoopFactors() {
-        for (LoopInfo info : loopInfos) {
-            double frequency = info.loopFrequency();
-            assert frequency != -1;
-        }
-    }
-
-    private static boolean isRelativeProbability(double prob) {
-        // 1.01 to allow for some rounding errors
-        return prob >= 0 && prob <= 1.01;
-    }
-
-    public static class LoopInfo {
-        public final LoopBeginNode loopBegin;
-
-        public final NodeMap<Set<LoopInfo>> requires;
-
-        private double loopFrequency = -1;
-        public boolean ended = false;
-
-        public LoopInfo(LoopBeginNode loopBegin) {
-            this.loopBegin = loopBegin;
-            this.requires = loopBegin.graph().createNodeMap();
-        }
-
-        public double loopFrequency() {
-            if (loopFrequency == -1 && ended) {
-                double backEdgeProb = 0.0;
-                for (LoopEndNode le : loopBegin.loopEnds()) {
-                    double factor = 1;
-                    Set<LoopInfo> requireds = requires.get(le);
-                    for (LoopInfo required : requireds) {
-                        double t = required.loopFrequency();
-                        if (t == -1) {
-                            return -1;
-                        }
-                        factor *= t;
-                    }
-                    backEdgeProb += le.probability() * factor;
-                }
-                double d = loopBegin.probability() - backEdgeProb;
-                if (d < EPSILON) {
-                    d = EPSILON;
-                }
-                loopFrequency = loopBegin.probability() / d;
-                loopBegin.setLoopFrequency(loopFrequency);
-            }
-            return loopFrequency;
-        }
-    }
-
-    public Set<LoopInfo> loopInfos = new HashSet<>();
-    public Map<MergeNode, Set<LoopInfo>> mergeLoops = new IdentityHashMap<>();
-
-    private class Probability implements MergeableState<Probability> {
-        public double probability;
-        public HashSet<LoopInfo> loops;
-        public LoopInfo loopInfo;
-
-        public Probability(double probability, HashSet<LoopInfo> loops) {
-            this.probability = probability;
-            this.loops = new HashSet<>(4);
-            if (loops != null) {
-                this.loops.addAll(loops);
-            }
-        }
-
-        @Override
-        public Probability clone() {
-            return new Probability(probability, loops);
-        }
-
-        @Override
-        public boolean merge(MergeNode merge, List<Probability> withStates) {
-            if (merge.forwardEndCount() > 1) {
-                HashSet<LoopInfo> intersection = new HashSet<>(loops);
-                for (Probability other : withStates) {
-                    intersection.retainAll(other.loops);
-                }
-                for (LoopInfo info : loops) {
-                    if (!intersection.contains(info)) {
-                        double loopFrequency = info.loopFrequency();
-                        if (loopFrequency == -1) {
-                            return false;
-                        }
-                        probability *= loopFrequency;
-                    }
-                }
-                for (Probability other : withStates) {
-                    double prob = other.probability;
-                    for (LoopInfo info : other.loops) {
-                        if (!intersection.contains(info)) {
-                            double loopFrequency = info.loopFrequency();
-                            if (loopFrequency == -1) {
-                                return false;
-                            }
-                            prob *= loopFrequency;
-                        }
-                    }
-                    probability += prob;
-                }
-                loops = intersection;
-                mergeLoops.put(merge, new HashSet<>(intersection));
-                assert isRelativeProbability(probability) : probability;
-            }
-            return true;
-        }
-
-        @Override
-        public void loopBegin(LoopBeginNode loopBegin) {
-            loopInfo = new LoopInfo(loopBegin);
-            loopInfos.add(loopInfo);
-            loops.add(loopInfo);
-        }
-
-        @Override
-        public void loopEnds(LoopBeginNode loopBegin, List<Probability> loopEndStates) {
-            assert loopInfo != null;
-            List<LoopEndNode> loopEnds = loopBegin.orderedLoopEnds();
-            int i = 0;
-            for (Probability proba : loopEndStates) {
-                LoopEndNode loopEnd = loopEnds.get(i++);
-                Set<LoopInfo> requires = loopInfo.requires.get(loopEnd);
-                if (requires == null) {
-                    requires = new HashSet<>();
-                    loopInfo.requires.set(loopEnd, requires);
-                }
-                for (LoopInfo innerLoop : proba.loops) {
-                    if (innerLoop != loopInfo && !this.loops.contains(innerLoop)) {
-                        requires.add(innerLoop);
-                    }
-                }
-            }
-            loopInfo.ended = true;
-        }
-
-        @Override
-        public void afterSplit(FixedNode node) {
-            assert node.predecessor() != null;
-            Node pred = node.predecessor();
-            if (pred instanceof Invoke) {
-                Invoke x = (Invoke) pred;
-                if (x.next() != node) {
-                    probability = 0;
-                }
-            } else {
-                assert pred instanceof ControlSplitNode;
-                ControlSplitNode x = (ControlSplitNode) pred;
-                double sum = 0;
-                for (int i = 0; i < x.blockSuccessorCount(); i++) {
-                    if (x.blockSuccessor(i) == node) {
-                        sum += x.probability(i);
-                    }
-                }
-                probability *= sum;
-            }
-        }
-    }
-
-    private class PropagateProbability extends PostOrderNodeIterator<Probability> {
-
-        public PropagateProbability(FixedNode start) {
-            super(start, new Probability(1d, null));
-        }
-
-        @Override
-        protected void node(FixedNode node) {
-            node.setProbability(state.probability);
-        }
-    }
-
-    private class LoopCount implements MergeableState<LoopCount> {
-        public double count;
-
-        public LoopCount(double count) {
-            this.count = count;
-        }
-
-        @Override
-        public LoopCount clone() {
-            return new LoopCount(count);
-        }
-
-        @Override
-        public boolean merge(MergeNode merge, List<LoopCount> withStates) {
-            assert merge.forwardEndCount() == withStates.size() + 1;
-            if (merge.forwardEndCount() > 1) {
-                Set<LoopInfo> loops = mergeLoops.get(merge);
-                assert loops != null;
-                double countProd = 1;
-                for (LoopInfo loop : loops) {
-                    countProd *= loop.loopFrequency();
-                }
-                count = countProd;
-            }
-            return true;
-        }
-
-        @Override
-        public void loopBegin(LoopBeginNode loopBegin) {
-            count *= loopBegin.loopFrequency();
-        }
-
-        @Override
-        public void loopEnds(LoopBeginNode loopBegin, List<LoopCount> loopEndStates) {
-            // nothing to do...
-        }
-
-        @Override
-        public void afterSplit(FixedNode node) {
-            // nothing to do...
-        }
-    }
-
-    private class PropagateLoopFrequency extends PostOrderNodeIterator<LoopCount> {
-
-        private final FrequencyPropagationPolicy policy;
-
-        public PropagateLoopFrequency(FixedNode start) {
-            super(start, new LoopCount(1d));
-            this.policy = createFrequencyPropagationPolicy();
-        }
-
-        @Override
-        protected void node(FixedNode node) {
-            node.setProbability(policy.compute(node.probability(), state.count));
-        }
-
-    }
-
-    private static FrequencyPropagationPolicy createFrequencyPropagationPolicy() {
-        switch (GraalOptions.LoopFrequencyPropagationPolicy) {
-            case -3:
-            case -2:
-            case -1:
-            case 0:
-                return new FullFrequencyPropagation();
-            case 1:
-                return new NoFrequencyPropagation();
-            default:
-                throw GraalInternalError.shouldNotReachHere();
-        }
-    }
-
-    private interface FrequencyPropagationPolicy {
-
-        double compute(double probability, double frequency);
-    }
-
-    private static class FullFrequencyPropagation implements FrequencyPropagationPolicy {
-
-        @Override
-        public double compute(double probability, double frequency) {
-            return probability * frequency;
-        }
-    }
-
-    private static class NoFrequencyPropagation implements FrequencyPropagationPolicy {
-
-        @Override
-        public double compute(double probability, double frequency) {
-            return probability;
-        }
-    }
-}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/ConvertDeoptimizeToGuardPhase.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.phases;
-
-import java.util.*;
-
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.util.*;
-
-public class ConvertDeoptimizeToGuardPhase extends Phase {
-
-    private static BeginNode findBeginNode(Node startNode) {
-        Node n = startNode;
-        while (true) {
-            if (n instanceof BeginNode) {
-                return (BeginNode) n;
-            } else {
-                n = n.predecessor();
-            }
-        }
-    }
-
-    @Override
-    protected void run(final StructuredGraph graph) {
-        if (graph.getNodes(DeoptimizeNode.class).isEmpty()) {
-            return;
-        }
-
-        for (DeoptimizeNode d : graph.getNodes(DeoptimizeNode.class)) {
-            visitDeoptBegin(findBeginNode(d), d, graph);
-        }
-
-        new DeadCodeEliminationPhase().apply(graph);
-    }
-
-    private void visitDeoptBegin(BeginNode deoptBegin, DeoptimizeNode deopt, StructuredGraph graph) {
-        if (deoptBegin instanceof MergeNode) {
-            MergeNode mergeNode = (MergeNode) deoptBegin;
-            Debug.log("Visiting %s followed by %s", mergeNode, deopt);
-            List<EndNode> ends = mergeNode.forwardEnds().snapshot();
-            for (EndNode end : ends) {
-                if (!end.isDeleted()) {
-                    BeginNode beginNode = findBeginNode(end);
-                    if (!(beginNode instanceof MergeNode)) {
-                        visitDeoptBegin(beginNode, deopt, graph);
-                    }
-                }
-            }
-            if (mergeNode.isDeleted()) {
-                if (!deopt.isDeleted()) {
-                    Debug.log("Merge deleted, deopt moved to %s", findBeginNode(deopt));
-                    visitDeoptBegin(findBeginNode(deopt), deopt, graph);
-                }
-            }
-        } else if (deoptBegin.predecessor() instanceof IfNode) {
-            IfNode ifNode = (IfNode) deoptBegin.predecessor();
-            BeginNode otherBegin = ifNode.trueSuccessor();
-            BooleanNode conditionNode = ifNode.compare();
-            boolean negated = false;
-            if (deoptBegin == ifNode.trueSuccessor()) {
-                negated = true;
-                otherBegin = ifNode.falseSuccessor();
-            }
-            BeginNode ifBlockBegin = findBeginNode(ifNode);
-            Debug.log("Converting %s on %-5s branch of %s to guard for remaining branch %s. IfBegin=%s", deopt, deoptBegin == ifNode.trueSuccessor() ? "true" : "false", ifNode, otherBegin, ifBlockBegin);
-            FixedGuardNode guard = graph.add(new FixedGuardNode(conditionNode, deopt.reason(), deopt.action(), negated, deopt.leafGraphId()));
-            otherBegin.replaceAtUsages(ifBlockBegin);
-            FixedNode next = otherBegin.next();
-            otherBegin.setNext(null);
-            guard.setNext(next);
-            ifNode.replaceAtPredecessor(guard);
-            GraphUtil.killCFG(ifNode);
-        }
-    }
-}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/ConvertUnreachedToGuardPhase.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 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 com.oracle.graal.compiler.phases;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.util.*;
-
-
-public class ConvertUnreachedToGuardPhase extends Phase {
-    private OptimisticOptimizations opt;
-
-    public ConvertUnreachedToGuardPhase(OptimisticOptimizations opt) {
-        this.opt = opt;
-    }
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        if (!opt.removeNeverExecutedCode()) {
-            return;
-        }
-        for (Node node : graph.getNodes()) {
-            if (node instanceof IfNode) {
-                IfNode ifNode = (IfNode) node;
-                BeginNode insertGuard = null;
-                BeginNode delete = null;
-                boolean inverted = false;
-                if (ifNode.probability(IfNode.TRUE_EDGE) == 0) {
-                    insertGuard = ifNode.falseSuccessor();
-                    delete = ifNode.trueSuccessor();
-                    inverted = true;
-                } else if (ifNode.probability(IfNode.FALSE_EDGE) == 0) {
-                    insertGuard = ifNode.trueSuccessor();
-                    delete = ifNode.falseSuccessor();
-                }
-                if (insertGuard != null) {
-                    GuardNode guard = graph.unique(new GuardNode(ifNode.compare(), BeginNode.prevBegin(ifNode), DeoptimizationReason.UnreachedCode, DeoptimizationAction.InvalidateReprofile, inverted, ifNode.leafGraphId()));
-                    graph.addBeforeFixed(ifNode, graph.add(new ValueAnchorNode(guard)));
-                    GraphUtil.killCFG(delete);
-                    graph.removeSplit(ifNode, inverted ? IfNode.FALSE_EDGE : IfNode.TRUE_EDGE);
-                }
-            }
-        }
-
-    }
-
-}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/CullFrameStatesPhase.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-/*
- * Copyright (c) 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 com.oracle.graal.compiler.phases;
-
-import java.util.*;
-
-import com.oracle.graal.compiler.graph.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.util.*;
-
-/**
- * This phase culls unused FrameStates from the graph.
- * It does a post order iteration over the graph, and
- */
-public class CullFrameStatesPhase extends Phase {
-
-    private static final DebugMetric metricFrameStatesCulled = Debug.metric("FrameStatesCulled");
-    private static final DebugMetric metricMergesTraversed = Debug.metric("MergesTraversed");
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        new CullFrameStates(graph.start(), new State(null)).apply();
-    }
-
-    public static class State implements MergeableState<State> {
-
-        private FrameState lastFrameState;
-
-        public State(FrameState lastFrameState) {
-            this.lastFrameState = lastFrameState;
-        }
-
-        @Override
-        public boolean merge(MergeNode merge, List<State> withStates) {
-            FrameState stateAfter = merge.stateAfter();
-            if (merge instanceof LoopBeginNode) {
-                if (stateAfter != null) {
-                    lastFrameState = stateAfter;
-                }
-                return true;
-            }
-            metricMergesTraversed.increment();
-            if (stateAfter != null) {
-                for (State other : withStates) {
-                    if (other.lastFrameState != lastFrameState) {
-                        lastFrameState = stateAfter;
-                        return true;
-                    }
-                }
-                metricFrameStatesCulled.increment();
-                merge.setStateAfter(null);
-                if (stateAfter.usages().isEmpty()) {
-                    GraphUtil.killWithUnusedFloatingInputs(stateAfter);
-                }
-            }
-            return true;
-        }
-
-        @Override
-        public void loopBegin(LoopBeginNode loopBegin) {
-        }
-
-        @Override
-        public void loopEnds(LoopBeginNode loopBegin, List<State> loopEndStates) {
-        }
-
-        @Override
-        public void afterSplit(FixedNode node) {
-        }
-
-        @Override
-        public State clone() {
-            return new State(lastFrameState);
-        }
-    }
-
-    public static class CullFrameStates extends PostOrderNodeIterator<State> {
-
-        public CullFrameStates(FixedNode start, State initialState) {
-            super(start, initialState);
-        }
-
-        @Override
-        protected void node(FixedNode node) {
-            if (node instanceof StateSplit) {
-                FrameState stateAfter = ((StateSplit) node).stateAfter();
-                if (stateAfter != null) {
-                    state.lastFrameState = stateAfter;
-                }
-            }
-        }
-    }
-
-}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/DeadCodeEliminationPhase.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,131 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.phases;
-
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-
-
-public class DeadCodeEliminationPhase extends Phase {
-
-    // Metrics
-    private static final DebugMetric metricNodesRemoved = Debug.metric("NodesRemoved");
-
-    private NodeFlood flood;
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        this.flood = graph.createNodeFlood();
-
-        flood.add(graph.start());
-        iterateSuccessors();
-        disconnectCFGNodes(graph);
-        iterateInputs(graph);
-        deleteNodes(graph);
-
-        // remove chained Merges
-        for (MergeNode merge : graph.getNodes(MergeNode.class)) {
-            if (merge.forwardEndCount() == 1 && !(merge instanceof LoopBeginNode)) {
-                graph.reduceTrivialMerge(merge);
-            }
-        }
-    }
-
-    private void iterateSuccessors() {
-        for (Node current : flood) {
-            if (current instanceof EndNode) {
-                EndNode end = (EndNode) current;
-                flood.add(end.merge());
-            } else {
-                for (Node successor : current.successors()) {
-                    flood.add(successor);
-                }
-            }
-        }
-    }
-
-    private void disconnectCFGNodes(StructuredGraph graph) {
-        for (EndNode node : graph.getNodes(EndNode.class)) {
-            if (!flood.isMarked(node)) {
-                MergeNode merge = node.merge();
-                if (merge != null && flood.isMarked(merge)) {
-                    // We are a dead end node leading to a live merge.
-                    merge.removeEnd(node);
-                }
-            }
-        }
-        for (LoopBeginNode loop : graph.getNodes(LoopBeginNode.class)) {
-            if (flood.isMarked(loop)) {
-                boolean reachable = false;
-                for (LoopEndNode end : loop.loopEnds()) {
-                    if (flood.isMarked(end)) {
-                        reachable = true;
-                        break;
-                    }
-                }
-                if (!reachable) {
-                    Debug.log("Removing loop with unreachable end: %s", loop);
-                    for (LoopEndNode end : loop.loopEnds().snapshot()) {
-                        loop.removeEnd(end);
-                    }
-                    graph.reduceDegenerateLoopBegin(loop);
-                }
-            }
-        }
-    }
-
-    private void deleteNodes(StructuredGraph graph) {
-        for (Node node : graph.getNodes()) {
-            if (!flood.isMarked(node)) {
-                node.clearInputs();
-                node.clearSuccessors();
-            }
-        }
-        for (Node node : graph.getNodes()) {
-            if (!flood.isMarked(node)) {
-                metricNodesRemoved.increment();
-                node.safeDelete();
-            }
-        }
-    }
-
-    private void iterateInputs(StructuredGraph graph) {
-        for (Node node : graph.getNodes()) {
-            if (node instanceof LocalNode) {
-                flood.add(node);
-            }
-            if (flood.isMarked(node)) {
-                for (Node input : node.inputs()) {
-                    flood.add(input);
-                }
-            }
-        }
-        for (Node current : flood) {
-            for (Node input : current.inputs()) {
-                flood.add(input);
-            }
-        }
-    }
-
-}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/ExpandBoxingNodesPhase.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.phases;
-
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
-
-public class ExpandBoxingNodesPhase extends Phase {
-
-    private final BoxingMethodPool pool;
-
-    public ExpandBoxingNodesPhase(BoxingMethodPool pool) {
-        this.pool = pool;
-    }
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        for (BoxNode boxNode : graph.getNodes(BoxNode.class)) {
-            boxNode.expand(pool);
-        }
-
-        for (UnboxNode unboxNode : graph.getNodes(UnboxNode.class)) {
-            unboxNode.expand(pool);
-        }
-    }
-}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/FloatingReadPhase.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,294 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.phases;
-
-import java.util.*;
-
-import com.oracle.graal.compiler.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.PhiNode.PhiType;
-import com.oracle.graal.nodes.extended.*;
-
-public class FloatingReadPhase extends Phase {
-
-    private IdentityHashMap<LoopBeginNode, List<MemoryMap>> loopEndStatesMap;
-
-    private static class LoopState {
-        public LoopBeginNode loopBegin;
-        public MemoryMap state;
-        public IdentityHashMap<PhiNode, Object> loopPhiLocations = new IdentityHashMap<>();
-        public ValueNode loopEntryAnyLocation;
-        public LoopState(LoopBeginNode loopBegin, MemoryMap state, ValueNode loopEntryAnyLocation) {
-            this.loopBegin = loopBegin;
-            this.state = state;
-            this.loopEntryAnyLocation = loopEntryAnyLocation;
-        }
-
-        @Override
-        public String toString() {
-            return "State@" + loopBegin;
-        }
-    }
-
-    private class MemoryMap implements MergeableState<MemoryMap> {
-        private IdentityHashMap<Object, ValueNode> lastMemorySnapshot;
-        private LinkedList<LoopState> loops;
-
-        public MemoryMap(MemoryMap memoryMap) {
-            lastMemorySnapshot = new IdentityHashMap<>(memoryMap.lastMemorySnapshot);
-            loops = new LinkedList<>(memoryMap.loops);
-        }
-
-        public MemoryMap() {
-            lastMemorySnapshot = new IdentityHashMap<>();
-            loops = new LinkedList<>();
-        }
-
-        @Override
-        public String toString() {
-            return "Map=" + lastMemorySnapshot.toString() + " Loops=" + loops.toString();
-        }
-
-        @Override
-        public boolean merge(MergeNode merge, List<MemoryMap> withStates) {
-            if (withStates.size() == 0) {
-                return true;
-            }
-
-            int minLoops = loops.size();
-            for (MemoryMap other : withStates) {
-                int otherLoops = other.loops.size();
-                if (otherLoops < minLoops) {
-                    minLoops = otherLoops;
-                }
-            }
-            while (loops.size() > minLoops) {
-                loops.pop();
-            }
-            for (MemoryMap other : withStates) {
-                while (other.loops.size() > minLoops) {
-                    other.loops.pop();
-                }
-            }
-
-            Set<Object> keys = new HashSet<>();
-            for (Object key : lastMemorySnapshot.keySet()) {
-                keys.add(key);
-            }
-            for (MemoryMap other : withStates) {
-                assert other.loops.size() == loops.size();
-                assert other.loops.size() < 1 || other.loops.peek().loopBegin == loops.peek().loopBegin;
-                for (Object key : other.lastMemorySnapshot.keySet()) {
-                    keys.add(key);
-                }
-            }
-            @SuppressWarnings("unchecked")
-            IdentityHashMap<Object, ValueNode> newMemorySnapshot = (IdentityHashMap<Object, ValueNode>) lastMemorySnapshot.clone();
-
-            for (Object key : keys) {
-                ValueNode merged = lastMemorySnapshot.get(key);
-                if (merged == null) {
-                    merged = lastMemorySnapshot.get(LocationNode.ANY_LOCATION);
-                }
-                int mergedStatesCount = 1;
-                boolean isPhi = false;
-                for (MemoryMap other : withStates) {
-                    ValueNode otherValue = other.lastMemorySnapshot.get(key);
-                    if (otherValue == null) {
-                        otherValue = other.lastMemorySnapshot.get(LocationNode.ANY_LOCATION);
-                    }
-                    if (isPhi) {
-                        ((PhiNode) merged).addInput(otherValue);
-                    } else if (merged != otherValue) {
-                        PhiNode phi = merge.graph().add(new PhiNode(PhiType.Memory, merge));
-                        for (int j = 0; j < mergedStatesCount; j++) {
-                            phi.addInput(merged);
-                        }
-                        phi.addInput(otherValue);
-                        merged = phi;
-                        isPhi = true;
-                        newMemorySnapshot.put(key, phi);
-                    }
-                    mergedStatesCount++;
-                }
-            }
-
-            lastMemorySnapshot = newMemorySnapshot;
-            return true;
-        }
-
-        @Override
-        public void loopBegin(LoopBeginNode loopBegin) {
-            LoopState loopState = new LoopState(loopBegin, this, lastMemorySnapshot.get(LocationNode.ANY_LOCATION));
-            for (Map.Entry<Object, ValueNode> entry : lastMemorySnapshot.entrySet()) {
-                PhiNode phi = loopBegin.graph().add(new PhiNode(PhiType.Memory, loopBegin));
-                phi.addInput(entry.getValue());
-                entry.setValue(phi);
-                loopState.loopPhiLocations.put(phi, entry.getKey());
-            }
-            loops.push(loopState);
-        }
-
-        @Override
-        public void loopEnds(LoopBeginNode loopBegin, List<MemoryMap> loopEndStates) {
-            loopEndStatesMap.put(loopBegin, loopEndStates);
-            tryFinishLoopPhis(this, loopBegin);
-        }
-
-        @Override
-        public void afterSplit(FixedNode node) {
-            // nothing
-        }
-
-        @Override
-        public MemoryMap clone() {
-            return new MemoryMap(this);
-        }
-    }
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        loopEndStatesMap = new IdentityHashMap<>();
-        new PostOrderNodeIterator<MemoryMap>(graph.start(), new MemoryMap()) {
-            @Override
-            protected void node(FixedNode node) {
-                processNode(node, state);
-            }
-        }.apply();
-    }
-
-    private void processNode(FixedNode node, MemoryMap state) {
-        if (node instanceof ReadNode) {
-            processRead((ReadNode) node, state);
-        } else if (node instanceof WriteNode) {
-            processWrite((WriteNode) node, state);
-        } else if (node instanceof MemoryCheckpoint) {
-            processCheckpoint((MemoryCheckpoint) node, state);
-        } else if (node instanceof LoopExitNode) {
-            processLoopExit((LoopExitNode) node, state);
-        }
-    }
-
-    private static void processCheckpoint(MemoryCheckpoint checkpoint, MemoryMap state) {
-        processAnyLocationWrite((ValueNode) checkpoint, state);
-    }
-
-    private static void processWrite(WriteNode writeNode, MemoryMap state) {
-        if (writeNode.location().locationIdentity() == LocationNode.ANY_LOCATION) {
-            processAnyLocationWrite(writeNode, state);
-        }
-        state.lastMemorySnapshot.put(writeNode.location().locationIdentity(), writeNode);
-    }
-
-    private static void processAnyLocationWrite(ValueNode modifiying, MemoryMap state) {
-        for (Map.Entry<Object, ValueNode> entry : state.lastMemorySnapshot.entrySet()) {
-            entry.setValue(modifiying);
-        }
-        state.lastMemorySnapshot.put(LocationNode.ANY_LOCATION, modifiying);
-        state.loops.clear();
-    }
-
-    private void processRead(ReadNode readNode, MemoryMap state) {
-        StructuredGraph graph = (StructuredGraph) readNode.graph();
-        assert readNode.getNullCheck() == false;
-        Object locationIdentity = readNode.location().locationIdentity();
-        ValueNode lastLocationAccess = getLastLocationAccessForRead(state, locationIdentity);
-        FloatingReadNode floatingRead = graph.unique(new FloatingReadNode(readNode.object(), readNode.location(), lastLocationAccess, readNode.stamp(), readNode.dependencies()));
-        floatingRead.setNullCheck(readNode.getNullCheck());
-        ValueAnchorNode anchor = null;
-        for (GuardNode guard : readNode.dependencies().filter(GuardNode.class)) {
-            if (anchor == null) {
-                anchor = graph.add(new ValueAnchorNode());
-            }
-            anchor.addAnchoredNode(guard);
-        }
-        if (anchor != null) {
-            graph.addAfterFixed(readNode, anchor);
-        }
-        graph.replaceFixedWithFloating(readNode, floatingRead);
-    }
-
-    private ValueNode getLastLocationAccessForRead(MemoryMap state, Object locationIdentity) {
-        ValueNode lastLocationAccess;
-        if (locationIdentity == LocationNode.FINAL_LOCATION) {
-            lastLocationAccess = null;
-        } else {
-            lastLocationAccess = state.lastMemorySnapshot.get(locationIdentity);
-            if (lastLocationAccess == null) {
-                LoopState lastLoop = state.loops.peek();
-                if (lastLoop == null) {
-                    lastLocationAccess = state.lastMemorySnapshot.get(LocationNode.ANY_LOCATION);
-                } else {
-                    ValueNode phiInit;
-                    if (state.loops.size() > 1) {
-                        phiInit = getLastLocationAccessForRead(state.loops.get(1).state, locationIdentity);
-                    } else {
-                        phiInit = lastLoop.loopEntryAnyLocation;
-                    }
-                    PhiNode phi = lastLoop.loopBegin.graph().add(new PhiNode(PhiType.Memory, lastLoop.loopBegin));
-                    phi.addInput(phiInit);
-                    lastLoop.state.lastMemorySnapshot.put(locationIdentity, phi);
-                    lastLoop.loopPhiLocations.put(phi, locationIdentity);
-                    tryFinishLoopPhis(lastLoop.state, lastLoop.loopBegin);
-                    lastLocationAccess = phi;
-                }
-                state.lastMemorySnapshot.put(locationIdentity, lastLocationAccess);
-            }
-        }
-        return lastLocationAccess;
-    }
-
-    private static void processLoopExit(LoopExitNode exit, MemoryMap state) {
-        for (Map.Entry<Object, ValueNode> entry : state.lastMemorySnapshot.entrySet()) {
-            entry.setValue(exit.graph().unique(new ValueProxyNode(entry.getValue(), exit, PhiType.Memory)));
-        }
-        if (!state.loops.isEmpty()) {
-            state.loops.pop();
-        }
-    }
-
-    private void tryFinishLoopPhis(MemoryMap loopMemory, LoopBeginNode loopBegin) {
-        List<MemoryMap> loopEndStates = loopEndStatesMap.get(loopBegin);
-        if (loopEndStates == null) {
-            return;
-        }
-        LoopState loopState = loopMemory.loops.get(0);
-        int i = 0;
-        while (loopState.loopBegin != loopBegin) {
-            loopState = loopMemory.loops.get(++i);
-        }
-        for (PhiNode phi : loopBegin.phis()) {
-            if (phi.type() == PhiType.Memory && phi.valueCount() == 1) {
-                Object location = loopState.loopPhiLocations.get(phi);
-                assert location != null : "unknown location for " + phi;
-                for (MemoryMap endState : loopEndStates) {
-                    ValueNode otherNode = endState.lastMemorySnapshot.get(location);
-                    if (otherNode == null) {
-                        otherNode = endState.lastMemorySnapshot.get(LocationNode.ANY_LOCATION);
-                    }
-                    phi.addInput(otherNode);
-                }
-            }
-        }
-    }
-}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/GlobalValueNumberingPhase.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.phases;
-
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-
-public class GlobalValueNumberingPhase extends Phase {
-
-    public static final DebugMetric metricGlobalValueNumberingHits = Debug.metric("GlobalValueNumberingHits");
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        NodeBitMap visited = graph.createNodeBitMap();
-        for (Node n : graph.getNodes()) {
-            apply(n, visited, graph);
-        }
-    }
-
-    private void apply(Node n, NodeBitMap visited, StructuredGraph compilerGraph) {
-        if (!visited.isMarked(n)) {
-            visited.mark(n);
-            for (Node input : n.inputs()) {
-                apply(input, visited, compilerGraph);
-            }
-            if (n.getNodeClass().valueNumberable()) {
-                Node newNode = compilerGraph.findDuplicate(n);
-                if (newNode != null) {
-                    assert !(n instanceof FixedNode || newNode instanceof FixedNode);
-                    n.replaceAtUsages(newNode);
-                    n.safeDelete();
-                    metricGlobalValueNumberingHits.increment();
-                    Debug.log("GVN applied and new node is %1s", newNode);
-                }
-            }
-        }
-    }
-}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/IdentifyBoxingPhase.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.phases;
-
-import java.lang.reflect.*;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.java.*;
-
-public class IdentifyBoxingPhase extends Phase {
-
-    private final BoxingMethodPool pool;
-
-    public IdentifyBoxingPhase(BoxingMethodPool pool) {
-        this.pool = pool;
-    }
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        for (Invoke invoke : graph.getInvokes()) {
-            tryIntrinsify(invoke);
-        }
-    }
-
-    public void tryIntrinsify(Invoke invoke) {
-        if (!(invoke.callTarget() instanceof MethodCallTargetNode)) {
-            return;
-        }
-        MethodCallTargetNode callTarget = invoke.methodCallTarget();
-        ResolvedJavaMethod targetMethod = callTarget.targetMethod();
-        if (pool.isSpecialMethod(targetMethod)) {
-            assert callTarget.arguments().size() == 1 : "boxing/unboxing method must have exactly one argument";
-            Kind returnKind = callTarget.returnKind();
-            ValueNode sourceValue = callTarget.arguments().get(0);
-
-            // Check whether this is a boxing or an unboxing.
-            Node newNode = null;
-            if (returnKind == Kind.Object) {
-                // We have a boxing method here.
-                assert Modifier.isStatic(targetMethod.accessFlags()) : "boxing method must be static";
-                Kind sourceKind = targetMethod.signature().argumentKindAt(0);
-                newNode = invoke.graph().add(new BoxNode(sourceValue, targetMethod.holder(), sourceKind, invoke.bci()));
-            } else {
-                // We have an unboxing method here.
-                assert !Modifier.isStatic(targetMethod.accessFlags()) : "unboxing method must be an instance method";
-                newNode = invoke.graph().add(new UnboxNode(returnKind, sourceValue));
-            }
-
-            // Intrinsify the invoke to the special node.
-            invoke.intrinsify(newNode);
-        }
-    }
-}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/InliningPhase.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,421 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.phases;
-
-import java.lang.reflect.*;
-import java.util.*;
-import java.util.concurrent.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.phases.PhasePlan.PhasePosition;
-import com.oracle.graal.compiler.util.*;
-import com.oracle.graal.compiler.util.InliningUtil.InlineInfo;
-import com.oracle.graal.compiler.util.InliningUtil.InliningCallback;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.debug.internal.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.spi.*;
-
-
-public class InliningPhase extends Phase implements InliningCallback {
-    /*
-     * - Detect method which only call another method with some parameters set to constants: void foo(a) -> void foo(a, b) -> void foo(a, b, c) ...
-     *   These should not be taken into account when determining inlining depth.
-     * - honor the result of overrideInliningDecision(0, caller, invoke.bci, method, true);
-     */
-
-    private final TargetDescription target;
-    private final GraalCodeCacheProvider runtime;
-
-    private final Collection<? extends Invoke> hints;
-
-    private final PriorityQueue<InlineInfo> inlineCandidates = new PriorityQueue<>();
-    private Assumptions assumptions;
-
-    private final PhasePlan plan;
-    private final GraphCache cache;
-    private final WeightComputationPolicy weightComputationPolicy;
-    private final InliningPolicy inliningPolicy;
-    private final OptimisticOptimizations optimisticOpts;
-
-    // Metrics
-    private static final DebugMetric metricInliningPerformed = Debug.metric("InliningPerformed");
-    private static final DebugMetric metricInliningConsidered = Debug.metric("InliningConsidered");
-    private static final DebugMetric metricInliningStoppedByMaxDesiredSize = Debug.metric("InliningStoppedByMaxDesiredSize");
-
-    public InliningPhase(TargetDescription target, GraalCodeCacheProvider runtime, Collection<? extends Invoke> hints, Assumptions assumptions, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts) {
-        this.target = target;
-        this.runtime = runtime;
-        this.hints = hints;
-        this.assumptions = assumptions;
-        this.cache = cache;
-        this.plan = plan;
-        this.optimisticOpts = optimisticOpts;
-        this.weightComputationPolicy = createWeightComputationPolicy();
-        this.inliningPolicy = createInliningPolicy();
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    protected void run(final StructuredGraph graph) {
-        graph.createNodeMap();
-
-        if (hints != null) {
-            scanInvokes((Iterable<? extends Node>) Util.uncheckedCast(this.hints));
-        } else {
-            scanInvokes(graph.getNodes(InvokeNode.class));
-            scanInvokes(graph.getNodes(InvokeWithExceptionNode.class));
-        }
-
-        while (!inlineCandidates.isEmpty() && graph.getNodeCount() < GraalOptions.MaximumDesiredSize) {
-            InlineInfo candidate = inlineCandidates.remove();
-            if (!candidate.invoke.node().isAlive()) {
-                continue;
-            }
-            // refresh infos
-            final InlineInfo info = InliningUtil.getInlineInfo(candidate.invoke, candidate.level, runtime, assumptions, this, optimisticOpts);
-
-            boolean inline = Debug.scope("InliningDecisions", new Callable<Boolean>() {
-                @Override
-                public Boolean call() throws Exception {
-                    return info != null && inliningPolicy.isWorthInlining(graph, info);
-                }
-            });
-
-            if (inline) {
-                int mark = graph.getMark();
-                Iterable<Node> newNodes = null;
-                try {
-                    info.inline(graph, runtime, this);
-                    Debug.dump(graph, "after %s", info);
-                    newNodes = graph.getNewNodes(mark);
-                    if (GraalOptions.OptCanonicalizer) {
-                        new CanonicalizerPhase(target, runtime, assumptions, mark, null).apply(graph);
-                    }
-//                    if (GraalOptions.Intrinsify) {
-//                        new IntrinsificationPhase(runtime).apply(graph);
-//                    }
-                    metricInliningPerformed.increment();
-                } catch (BailoutException bailout) {
-                    // TODO determine if we should really bail out of the whole compilation.
-                    throw bailout;
-                } catch (AssertionError e) {
-                    throw new GraalInternalError(e).addContext(info.toString());
-                } catch (RuntimeException e) {
-                    throw new GraalInternalError(e).addContext(info.toString());
-                } catch (GraalInternalError e) {
-                    throw e.addContext(info.toString());
-                }
-
-                if (newNodes != null && info.level < GraalOptions.MaximumInlineLevel) {
-                    scanInvokes(newNodes);
-                }
-            }
-        }
-
-        if (GraalOptions.Debug && graph.getNodeCount() >= GraalOptions.MaximumDesiredSize) {
-            Debug.scope("InliningDecisions", new Runnable() {
-                public void run() {
-                    for (InlineInfo info : inlineCandidates) {
-                        Debug.log("not inlining %s because inlining cut off by MaximumDesiredSize", InliningUtil.methodName(info));
-                    }
-                }
-            });
-
-            metricInliningStoppedByMaxDesiredSize.increment();
-        }
-    }
-
-    private void scanInvokes(final Iterable<? extends Node> nodes) {
-        Debug.scope("InliningDecisions", new Runnable() {
-            public void run() {
-                for (Node node : nodes) {
-                    if (node != null) {
-                        if (node instanceof Invoke) {
-                            Invoke invoke = (Invoke) node;
-                            scanInvoke(invoke);
-                        }
-                        for (Node usage : node.usages().filterInterface(Invoke.class).snapshot()) {
-                            scanInvoke((Invoke) usage);
-                        }
-                    }
-                }
-            }
-        });
-    }
-
-    private void scanInvoke(Invoke invoke) {
-        InlineInfo info = InliningUtil.getInlineInfo(invoke, computeInliningLevel(invoke), runtime, assumptions, this, optimisticOpts);
-        if (info != null) {
-            metricInliningConsidered.increment();
-            inlineCandidates.add(info);
-        }
-    }
-
-    public static final Map<JavaMethod, Integer> parsedMethods = new HashMap<>();
-
-
-
-    private static final DebugMetric metricInliningRuns = Debug.metric("Runs");
-
-    @Override
-    public StructuredGraph buildGraph(final ResolvedJavaMethod method) {
-        metricInliningRuns.increment();
-        if (GraalOptions.CacheGraphs && cache != null) {
-            StructuredGraph cachedGraph = cache.get(method);
-            if (cachedGraph != null) {
-                return cachedGraph;
-            }
-        }
-        StructuredGraph newGraph = new StructuredGraph(method);
-        if (plan != null) {
-            plan.runPhases(PhasePosition.AFTER_PARSING, newGraph);
-        }
-        assert newGraph.start().next() != null : "graph needs to be populated during PhasePosition.AFTER_PARSING";
-
-        if (GraalOptions.ProbabilityAnalysis) {
-            new DeadCodeEliminationPhase().apply(newGraph);
-            new ComputeProbabilityPhase().apply(newGraph);
-        }
-        if (GraalOptions.OptCanonicalizer) {
-            new CanonicalizerPhase(target, runtime, assumptions).apply(newGraph);
-        }
-        if (GraalOptions.Intrinsify) {
-            new IntrinsificationPhase(runtime).apply(newGraph);
-        }
-        if (GraalOptions.CullFrameStates) {
-            new CullFrameStatesPhase().apply(newGraph);
-        }
-        if (GraalOptions.CacheGraphs && cache != null) {
-            cache.put(newGraph);
-        }
-        return newGraph;
-    }
-
-    @Override
-    public double inliningWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke) {
-        boolean preferred = hints != null && hints.contains(invoke);
-        return weightComputationPolicy.computeWeight(caller, method, invoke, preferred);
-    }
-
-    public static int graphComplexity(StructuredGraph graph) {
-        int result = 0;
-        for (Node node : graph.getNodes()) {
-            if (node instanceof ConstantNode || node instanceof LocalNode || node instanceof BeginNode || node instanceof ReturnNode || node instanceof UnwindNode) {
-                result += 0;
-            } else if (node instanceof PhiNode) {
-                result += 5;
-            } else if (node instanceof MergeNode || node instanceof Invoke || node instanceof LoopEndNode || node instanceof EndNode) {
-                result += 0;
-            } else if (node instanceof ControlSplitNode) {
-                result += ((ControlSplitNode) node).blockSuccessorCount();
-            } else {
-                result += 1;
-            }
-        }
-        return Math.max(1, result);
-    }
-
-
-    @Override
-    public void recordConcreteMethodAssumption(ResolvedJavaMethod method, ResolvedJavaType context, ResolvedJavaMethod impl) {
-        assumptions.recordConcreteMethod(method, context, impl);
-    }
-
-    @Override
-    public void recordMethodContentsAssumption(ResolvedJavaMethod method) {
-        if (assumptions != null) {
-            assumptions.recordMethodContents(method);
-        }
-    }
-
-    private static int computeInliningLevel(Invoke invoke) {
-        int count = -1;
-        FrameState curState = invoke.stateAfter();
-        while (curState != null) {
-            count++;
-            curState = curState.outerFrameState();
-        }
-        return count;
-    }
-
-    private static InliningPolicy createInliningPolicy() {
-        switch(GraalOptions.InliningPolicy) {
-            case 0: return new WeightBasedInliningPolicy();
-            case 1: return new C1StaticSizeBasedInliningPolicy();
-            case 2: return new MinimumCodeSizeBasedInliningPolicy();
-            case 3: return new DynamicSizeBasedInliningPolicy();
-            case 4: return new GreedySizeBasedInliningPolicy();
-            default:
-                GraalInternalError.shouldNotReachHere();
-                return null;
-        }
-    }
-
-    private static WeightComputationPolicy createWeightComputationPolicy() {
-        switch(GraalOptions.WeightComputationPolicy) {
-            case 0: throw new GraalInternalError("removed because of invokation counter changes");
-            case 1: return new BytecodeSizeBasedWeightComputationPolicy();
-            case 2: return new ComplexityBasedWeightComputationPolicy();
-            default:
-                GraalInternalError.shouldNotReachHere();
-                return null;
-        }
-    }
-
-    private interface InliningPolicy {
-        boolean isWorthInlining(StructuredGraph callerGraph, InlineInfo info);
-    }
-
-    private static class WeightBasedInliningPolicy implements InliningPolicy {
-        @Override
-        public boolean isWorthInlining(StructuredGraph callerGraph, InlineInfo info) {
-            if (!checkCompiledCodeSize(info)) {
-                return false;
-            }
-
-            double penalty = Math.pow(GraalOptions.InliningSizePenaltyExp, callerGraph.getNodeCount() / (double) GraalOptions.MaximumDesiredSize) / GraalOptions.InliningSizePenaltyExp;
-            if (info.weight > GraalOptions.MaximumInlineWeight / (1 + penalty * GraalOptions.InliningSizePenalty)) {
-                Debug.log("not inlining %s (cut off by weight %e)", InliningUtil.methodName(info), info.weight);
-                return false;
-            }
-
-            Debug.log("inlining %s (weight %f): %s", InliningUtil.methodName(info), info.weight);
-            return true;
-        }
-    }
-
-    private static class C1StaticSizeBasedInliningPolicy implements InliningPolicy {
-        @Override
-        public boolean isWorthInlining(StructuredGraph callerGraph, InlineInfo info) {
-            double maxSize = Math.max(GraalOptions.MaximumTrivialSize, Math.pow(GraalOptions.NestedInliningSizeRatio, info.level) * GraalOptions.MaximumInlineSize);
-            return decideSizeBasedInlining(info, maxSize);
-        }
-    }
-
-    private static class MinimumCodeSizeBasedInliningPolicy implements InliningPolicy {
-        @Override
-        public boolean isWorthInlining(StructuredGraph callerGraph, InlineInfo info) {
-            assert GraalOptions.ProbabilityAnalysis;
-            if (!checkCompiledCodeSize(info)) {
-                return false;
-            }
-
-            double inlineWeight = Math.min(GraalOptions.ProbabilityCapForInlining, info.invoke.probability());
-            double maxSize = Math.pow(GraalOptions.NestedInliningSizeRatio, info.level) * GraalOptions.MaximumInlineSize * inlineWeight;
-            maxSize = Math.max(GraalOptions.MaximumTrivialSize, maxSize);
-
-            return decideSizeBasedInlining(info, maxSize);
-        }
-    }
-
-    private static class DynamicSizeBasedInliningPolicy implements InliningPolicy {
-        @Override
-        public boolean isWorthInlining(StructuredGraph callerGraph, InlineInfo info) {
-            assert GraalOptions.ProbabilityAnalysis;
-            if (!checkCompiledCodeSize(info)) {
-                return false;
-            }
-
-            double inlineBoost = Math.min(GraalOptions.ProbabilityCapForInlining, info.invoke.probability()) + Math.log10(Math.max(1, info.invoke.probability() - GraalOptions.ProbabilityCapForInlining + 1));
-            double maxSize = Math.pow(GraalOptions.NestedInliningSizeRatio, info.level) * GraalOptions.MaximumInlineSize;
-            maxSize = maxSize + maxSize * inlineBoost;
-            maxSize = Math.min(GraalOptions.MaximumGreedyInlineSize, Math.max(GraalOptions.MaximumTrivialSize, maxSize));
-
-            return decideSizeBasedInlining(info, maxSize);
-        }
-    }
-
-    private static class GreedySizeBasedInliningPolicy implements InliningPolicy {
-        @Override
-        public boolean isWorthInlining(StructuredGraph callerGraph, InlineInfo info) {
-            assert GraalOptions.ProbabilityAnalysis;
-            if (!checkCompiledCodeSize(info)) {
-                return false;
-            }
-
-            double maxSize = GraalOptions.MaximumGreedyInlineSize;
-            if (GraalOptions.InliningBonusPerTransferredValue != 0) {
-                Signature signature = info.invoke.methodCallTarget().targetMethod().signature();
-                int transferredValues = signature.argumentCount(!Modifier.isStatic(info.invoke.methodCallTarget().targetMethod().accessFlags()));
-                if (signature.returnKind() != Kind.Void) {
-                    transferredValues++;
-                }
-                maxSize += transferredValues * GraalOptions.InliningBonusPerTransferredValue;
-            }
-
-            double inlineRatio = Math.min(GraalOptions.ProbabilityCapForInlining, info.invoke.probability());
-            maxSize = Math.pow(GraalOptions.NestedInliningSizeRatio, info.level) * maxSize * inlineRatio;
-            maxSize = Math.max(maxSize, GraalOptions.MaximumTrivialSize);
-
-            return decideSizeBasedInlining(info, maxSize);
-        }
-    }
-
-    private static boolean decideSizeBasedInlining(InlineInfo info, double maxSize) {
-        boolean success = info.weight <= maxSize;
-        if (DebugScope.getInstance().isLogEnabled()) {
-            String formatterString = success ? "inlining %s (size %f <= %f)" : "not inlining %s (too large %f > %f)";
-            Debug.log(formatterString, InliningUtil.methodName(info), info.weight, maxSize);
-        }
-        return success;
-    }
-
-    private static boolean checkCompiledCodeSize(InlineInfo info) {
-        if (GraalOptions.SmallCompiledCodeSize >= 0 && info.compiledCodeSize() > GraalOptions.SmallCompiledCodeSize) {
-            Debug.log("not inlining %s (CompiledCodeSize %d > %d)", InliningUtil.methodName(info), info.compiledCodeSize(), GraalOptions.SmallCompiledCodeSize);
-            return false;
-        }
-        return true;
-    }
-
-
-    private interface WeightComputationPolicy {
-        double computeWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke, boolean preferredInvoke);
-    }
-
-    private static class BytecodeSizeBasedWeightComputationPolicy implements WeightComputationPolicy {
-        @Override
-        public double computeWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke, boolean preferredInvoke) {
-            double codeSize = method.codeSize();
-            if (preferredInvoke) {
-                codeSize = codeSize / GraalOptions.BoostInliningForEscapeAnalysis;
-            }
-            return codeSize;
-        }
-    }
-
-    private static class ComplexityBasedWeightComputationPolicy implements WeightComputationPolicy {
-        @Override
-        public double computeWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke, boolean preferredInvoke) {
-            double complexity = method.compilationComplexity();
-            if (preferredInvoke) {
-                complexity = complexity / GraalOptions.BoostInliningForEscapeAnalysis;
-            }
-            return complexity;
-        }
-    }
-}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/InsertStateAfterPlaceholderPhase.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 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 com.oracle.graal.compiler.phases;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
-
-public class InsertStateAfterPlaceholderPhase extends Phase {
-
-    private static class PlaceholderNode extends AbstractStateSplit implements StateSplit, Node.IterableNodeType, LIRLowerable, Canonicalizable {
-        public PlaceholderNode() {
-            super(StampFactory.forVoid());
-        }
-
-        @Override
-        public void generate(LIRGeneratorTool gen) {
-            // nothing to do
-        }
-
-        @Override
-        public boolean hasSideEffect(CodeCacheProvider runtime) {
-            return false;
-        }
-
-        @Override
-        public ValueNode canonical(CanonicalizerTool tool) {
-            if (stateAfter() == null) {
-                return null;
-            }
-            return this;
-        }
-    }
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        for (ReturnNode ret : graph.getNodes(ReturnNode.class)) {
-            PlaceholderNode p = graph.add(new PlaceholderNode());
-            p.setStateAfter(graph.add(new FrameState(FrameState.AFTER_BCI)));
-            graph.addBeforeFixed(ret, p);
-        }
-    }
-
-}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/IntrinsificationPhase.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.phases;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.util.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.spi.*;
-
-public class IntrinsificationPhase extends Phase {
-
-    private final GraalCodeCacheProvider runtime;
-
-    public IntrinsificationPhase(GraalCodeCacheProvider runtime) {
-        this.runtime = runtime;
-    }
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        for (InvokeNode invoke : graph.getNodes(InvokeNode.class)) {
-            tryIntrinsify(invoke, runtime);
-        }
-        for (InvokeWithExceptionNode invoke : graph.getNodes(InvokeWithExceptionNode.class)) {
-            tryIntrinsify(invoke, runtime);
-        }
-    }
-
-    public static boolean canIntrinsify(Invoke invoke, ResolvedJavaMethod target, GraalCodeCacheProvider runtime) {
-        return getIntrinsicGraph(invoke, target, runtime) != null;
-    }
-
-    private static void tryIntrinsify(Invoke invoke, GraalCodeCacheProvider runtime) {
-        if (invoke.callTarget() instanceof MethodCallTargetNode && invoke.methodCallTarget().targetMethod() != null) {
-            tryIntrinsify(invoke, invoke.methodCallTarget().targetMethod(), runtime);
-        }
-    }
-
-    private static void tryIntrinsify(Invoke invoke, ResolvedJavaMethod target, GraalCodeCacheProvider runtime) {
-        StructuredGraph intrinsicGraph = getIntrinsicGraph(invoke, target, runtime);
-        if (intrinsicGraph != null) {
-            Debug.log(" > Intrinsify %s", target);
-            InliningUtil.inline(invoke, intrinsicGraph, true);
-        }
-    }
-
-    private static StructuredGraph getIntrinsicGraph(Invoke invoke, ResolvedJavaMethod target, GraalCodeCacheProvider runtime) {
-        StructuredGraph intrinsicGraph = (StructuredGraph) target.compilerStorage().get(Graph.class);
-        if (intrinsicGraph == null) {
-            // TODO remove once all intrinsics are available via compilerStorage
-            intrinsicGraph = runtime.intrinsicGraph(invoke.stateAfter().method(), invoke.bci(), target, invoke.callTarget().arguments());
-        }
-        return intrinsicGraph;
-    }
-}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/IterativeCheckCastEliminationPhase.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-/*
- * Copyright (c) 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 com.oracle.graal.compiler.phases;
-
-import java.util.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.Graph.InputChangedListener;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-
-
-public class IterativeCheckCastEliminationPhase extends Phase {
-    private final TargetDescription target;
-    private final MetaAccessProvider runtime;
-    private final Assumptions assumptions;
-
-    public IterativeCheckCastEliminationPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions) {
-        this.target = target;
-        this.runtime = runtime;
-        this.assumptions = assumptions;
-    }
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        Set<Node> canonicalizationRoots = new HashSet<>();
-        CheckCastEliminationPhase eliminate = new CheckCastEliminationPhase();
-        Listener listener = new Listener(canonicalizationRoots);
-        while (true) {
-            graph.trackInputChange(listener);
-            eliminate.apply(graph);
-            graph.stopTrackingInputChange();
-            if (canonicalizationRoots.isEmpty()) {
-                break;
-            }
-            new CanonicalizerPhase(target, runtime, assumptions, canonicalizationRoots, null).apply(graph);
-            canonicalizationRoots.clear();
-        }
-    }
-
-    private static class Listener implements InputChangedListener {
-        private final Set<Node> canonicalizationRoots;
-        public Listener(Set<Node> canonicalizationRoots) {
-            this.canonicalizationRoots = canonicalizationRoots;
-        }
-        @Override
-        public void inputChanged(Node node) {
-            canonicalizationRoots.add(node);
-        }
-    }
-}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/LoopSafepointInsertionPhase.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.phases;
-
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.graph.iterators.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.util.*;
-
-/**
- * Adds safepoints to loops.
- */
-public class LoopSafepointInsertionPhase extends Phase {
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        nextLoop:
-        for (LoopEndNode loopEnd : graph.getNodes(LoopEndNode.class)) {
-            if (!loopEnd.canSafepoint()) {
-                continue;
-            }
-            if (GraalOptions.OptSafepointElimination) {
-                // We 'eliminate' safepoints by simply never placing them into loops that have at least one call
-                NodeIterable<FixedNode> it = NodeIterators.dominators(loopEnd).until(loopEnd.loopBegin());
-                for (FixedNode n : it) {
-                    if (n instanceof Invoke) {
-                        continue nextLoop;
-                    }
-                }
-            }
-            SafepointNode safepoint = graph.add(new SafepointNode());
-            graph.addBeforeFixed(loopEnd, safepoint);
-        }
-    }
-}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/LoweringPhase.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,203 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.phases;
-
-import java.util.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.schedule.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.iterators.*;
-import com.oracle.graal.lir.cfg.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.spi.*;
-
-/**
- * Processes all {@link Lowerable} nodes to do their lowering.
- */
-public class LoweringPhase extends Phase {
-
-    final class LoweringToolImpl implements LoweringTool {
-
-        final FixedNode guardAnchor;
-        final NodeBitMap activeGuards;
-        FixedWithNextNode lastFixedNode;
-
-        public LoweringToolImpl(FixedNode guardAnchor, NodeBitMap activeGuards) {
-            this.guardAnchor = guardAnchor;
-            this.activeGuards = activeGuards;
-        }
-
-        @Override
-        public GraalCodeCacheProvider getRuntime() {
-            return runtime;
-        }
-
-        @Override
-        public ValueNode createNullCheckGuard(ValueNode object, long leafGraphId) {
-            return createGuard(object.graph().unique(new IsNullNode(object)), DeoptimizationReason.NullCheckException, DeoptimizationAction.InvalidateReprofile, true, leafGraphId);
-        }
-
-        @Override
-        public ValueNode createGuard(BooleanNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, long leafGraphId) {
-            return createGuard(condition, deoptReason, action, false, leafGraphId);
-        }
-
-        @Override
-        public Assumptions assumptions() {
-            return assumptions;
-        }
-
-        @Override
-        public ValueNode createGuard(BooleanNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated, long leafGraphId) {
-            if (GraalOptions.OptEliminateGuards) {
-                for (Node usage : condition.usages()) {
-                    if (!activeGuards.isNew(usage) && activeGuards.isMarked(usage)) {
-                        return (ValueNode) usage;
-                    }
-                }
-            }
-            GuardNode newGuard = guardAnchor.graph().unique(new GuardNode(condition, guardAnchor, deoptReason, action, negated, leafGraphId));
-            if (GraalOptions.OptEliminateGuards) {
-                activeGuards.grow();
-                activeGuards.mark(newGuard);
-            }
-            return newGuard;
-        }
-
-        public FixedWithNextNode lastFixedNode() {
-            return lastFixedNode;
-        }
-    }
-
-    private final GraalCodeCacheProvider runtime;
-    private final Assumptions assumptions;
-
-    public LoweringPhase(GraalCodeCacheProvider runtime, Assumptions assumptions) {
-        this.runtime = runtime;
-        this.assumptions = assumptions;
-    }
-
-    private static boolean containsLowerable(NodeIterable<Node> nodes) {
-        for (Node n : nodes) {
-            if (n instanceof Lowerable) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    protected void run(final StructuredGraph graph) {
-        int  i = 0;
-        NodeBitMap processed = graph.createNodeBitMap();
-        while (true) {
-            int mark = graph.getMark();
-            final SchedulePhase schedule = new SchedulePhase();
-            schedule.apply(graph, false);
-
-            processBlock(schedule.getCFG().getStartBlock(), graph.createNodeBitMap(), null, schedule, processed);
-            Debug.dump(graph, "Lowering iteration %d", i++);
-            new CanonicalizerPhase(null, runtime, assumptions, mark, null).apply(graph);
-
-            if (!containsLowerable(graph.getNewNodes(mark))) {
-                // No new lowerable nodes - done!
-                break;
-            }
-            assert graph.verify();
-            processed.grow();
-        }
-    }
-
-    private void processBlock(Block block, NodeBitMap activeGuards, FixedNode parentAnchor, SchedulePhase schedule, NodeBitMap processed) {
-
-        FixedNode anchor = parentAnchor;
-        if (anchor == null) {
-            anchor = block.getBeginNode();
-        }
-        process(block, activeGuards, anchor, schedule, processed);
-
-        // Process always reached block first.
-        Block alwaysReachedBlock = block.getPostdominator();
-        if (alwaysReachedBlock != null && alwaysReachedBlock.getDominator() == block) {
-            processBlock(alwaysReachedBlock, activeGuards, anchor, schedule, processed);
-        }
-
-        // Now go for the other dominators.
-        for (Block dominated : block.getDominated()) {
-            if (dominated != alwaysReachedBlock) {
-                assert dominated.getDominator() == block;
-                processBlock(dominated, activeGuards, null, schedule, processed);
-            }
-        }
-
-        if (parentAnchor == null && GraalOptions.OptEliminateGuards) {
-            for (GuardNode guard : anchor.usages().filter(GuardNode.class)) {
-                activeGuards.clear(guard);
-            }
-        }
-    }
-
-    private void process(final Block b, final NodeBitMap activeGuards, final FixedNode anchor, SchedulePhase schedule, NodeBitMap processed) {
-
-        final LoweringToolImpl loweringTool = new LoweringToolImpl(anchor, activeGuards);
-
-        // Lower the instructions of this block.
-        List<ScheduledNode> nodes = schedule.nodesFor(b);
-
-        for (Node node : nodes) {
-            FixedNode lastFixedNext = null;
-            if (node instanceof FixedWithNextNode) {
-                FixedWithNextNode fixed = (FixedWithNextNode) node;
-                lastFixedNext = fixed.next();
-                loweringTool.lastFixedNode = fixed;
-            }
-
-            if (node.isAlive() && !processed.isMarked(node)) {
-                processed.mark(node);
-                if (node instanceof Lowerable) {
-                    ((Lowerable) node).lower(loweringTool);
-                }
-            }
-
-            if (loweringTool.lastFixedNode == node && !node.isAlive()) {
-                if (lastFixedNext == null) {
-                    loweringTool.lastFixedNode = null;
-                } else {
-                    Node prev = lastFixedNext.predecessor();
-                    if (prev != node && prev instanceof FixedWithNextNode) {
-                        loweringTool.lastFixedNode = (FixedWithNextNode) prev;
-                    } else if (lastFixedNext instanceof FixedWithNextNode) {
-                        loweringTool.lastFixedNode = (FixedWithNextNode) lastFixedNext;
-                    } else {
-                        loweringTool.lastFixedNode = null;
-                    }
-                }
-            }
-        }
-    }
-}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/Phase.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.phases;
-
-import com.oracle.graal.debug.*;
-import com.oracle.graal.nodes.*;
-
-public abstract class Phase {
-
-    private String name;
-    private static final DebugMetric metricPhaseRuns = Debug.metric("Runs");
-    protected static final DebugMetric METRIC_PROCESSED_NODES = Debug.metric("ProcessedNodes");
-
-    protected Phase() {
-        this.name = this.getClass().getSimpleName();
-        if (name.endsWith("Phase")) {
-            name = name.substring(0, name.length() - "Phase".length());
-        }
-    }
-
-    protected Phase(String name) {
-        this.name = name;
-    }
-
-    protected String getDetailedName() {
-        return getName();
-    }
-
-    public final void apply(final StructuredGraph graph) {
-        apply(graph, true);
-    }
-
-    public final void apply(final StructuredGraph graph, final boolean dumpGraph) {
-        Debug.scope(name, this, new Runnable() {
-            public void run() {
-                Phase.this.run(graph);
-                metricPhaseRuns.increment();
-                if (dumpGraph) {
-                    Debug.dump(graph, "After phase %s", name);
-                }
-                assert graph.verify();
-            }
-        });
-    }
-
-    public final String getName() {
-        return name;
-    }
-
-    protected abstract void run(StructuredGraph graph);
-}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/PhasePlan.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.phases;
-
-import java.util.*;
-
-import com.oracle.graal.nodes.*;
-
-/**
- * Tells the compiler about additional phases that need to be executed during compilation.
- */
-public class PhasePlan {
-    /**
-     * The compilation is split into the following sections:
-     * ========================================================================
-     * Period 1: High-level nodes. (Graph building)
-     * ========================================================================
-     * Runtime-specific lowering.
-     * ========================================================================
-     * Period 2: Mid-level nodes. (Memory dependence graph)
-     * ========================================================================
-     * Target-specific lowering, de-SSA.
-     * ========================================================================
-     * Period 3: Low-level nodes. (Register allocation, code generation)
-     * ========================================================================
-     *
-     * A compiler extension phase can chose to run at the end of periods 1-3.
-     */
-    public static enum PhasePosition {
-        AFTER_PARSING,
-        HIGH_LEVEL,
-        MID_LEVEL,
-        LOW_LEVEL
-    }
-
-    @SuppressWarnings("unchecked")
-    private final ArrayList<Phase>[] phases = new ArrayList[PhasePosition.values().length];
-    private final Set<Class<? extends Phase>> disabledPhases = new HashSet<>();
-
-    public void addPhase(PhasePosition pos, Phase phase) {
-        if (phases[pos.ordinal()] == null) {
-            phases[pos.ordinal()] = new ArrayList<>();
-        }
-        phases[pos.ordinal()].add(phase);
-    }
-
-    public void runPhases(PhasePosition pos, StructuredGraph graph) {
-        if (phases[pos.ordinal()] != null) {
-            for (Phase p : phases[pos.ordinal()]) {
-                p.apply(graph);
-            }
-        }
-    }
-
-    public void disablePhase(Class<? extends Phase> clazz) {
-        disabledPhases.add(clazz);
-    }
-
-    public boolean isPhaseDisabled(Class<? extends Phase> clazz) {
-        return disabledPhases.contains(clazz);
-    }
-}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/PhiStampPhase.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.phases;
-
-import com.oracle.graal.nodes.*;
-
-public class PhiStampPhase extends Phase {
-    @Override
-    protected void run(StructuredGraph graph) {
-        // Infer phis stopping at loop phis.
-        for (PhiNode phi : graph.getNodes(PhiNode.class)) {
-            inferPhi(phi);
-        }
-
-        // Start iterative inference for loop phis.
-        if (graph.hasLoops()) {
-            for (PhiNode phi : graph.getNodes(PhiNode.class)) {
-                if (phi.isLoopPhi()) {
-                    iterativeInferPhi(phi);
-                }
-            }
-        }
-    }
-
-    private void iterativeInferPhi(PhiNode phi) {
-        if (phi.inferPhiStamp()) {
-            for (PhiNode phiUsage : phi.usages().filter(PhiNode.class)) {
-                iterativeInferPhi(phiUsage);
-            }
-        }
-    }
-
-    private void inferPhi(PhiNode phi) {
-        for (PhiNode phiInput : phi.values().filter(PhiNode.class)) {
-            if (!phiInput.isLoopPhi()) {
-                inferPhi(phiInput);
-            }
-        }
-        phi.inferPhiStamp();
-    }
-}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/ReadEliminationPhase.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.phases;
-
-import java.util.*;
-
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.PhiNode.PhiType;
-import com.oracle.graal.nodes.extended.*;
-
-public class ReadEliminationPhase extends Phase {
-    private Queue<PhiNode> newPhis;
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        newPhis = new LinkedList<>();
-        for (FloatingReadNode n : graph.getNodes(FloatingReadNode.class)) {
-            if (isReadEliminable(n)) {
-                NodeMap<ValueNode> nodeMap = n.graph().createNodeMap();
-                ValueNode value = getValue(n, n.lastLocationAccess(), nodeMap);
-                Debug.log("Eliminated memory read %1.1s and replaced with node %s", n, value);
-                graph.replaceFloating(n, value);
-            }
-        }
-    }
-
-    private boolean isReadEliminable(FloatingReadNode n) {
-        return isWrites(n, n.lastLocationAccess(), n.graph().createNodeBitMap());
-    }
-
-    private boolean isWrites(FloatingReadNode n, Node lastLocationAccess, NodeBitMap visited) {
-        if (lastLocationAccess == null) {
-            return false;
-        }
-        if (visited.isMarked(lastLocationAccess)) {
-            return true; // dataflow loops must come from Phis assume them ok until proven wrong
-        }
-        if (lastLocationAccess instanceof ValueProxyNode) {
-            return isWrites(n, ((ValueProxyNode) lastLocationAccess).value(), visited);
-        }
-        if (lastLocationAccess instanceof WriteNode) {
-            WriteNode other = (WriteNode) lastLocationAccess;
-            return other.object() == n.object() && other.location() == n.location();
-        }
-        if (lastLocationAccess instanceof PhiNode) {
-            visited.mark(lastLocationAccess);
-            for (ValueNode value : ((PhiNode) lastLocationAccess).values()) {
-                if (!isWrites(n, value, visited)) {
-                    return false;
-                }
-            }
-            return true;
-        }
-        return false;
-    }
-
-    private ValueNode getValue(FloatingReadNode n, Node lastLocationAccess, NodeMap<ValueNode> nodeMap) {
-        ValueNode exisiting = nodeMap.get(lastLocationAccess);
-        if (exisiting != null) {
-            return exisiting;
-        }
-        if (lastLocationAccess instanceof ValueProxyNode) {
-            ValueProxyNode proxy = (ValueProxyNode) lastLocationAccess;
-            ValueNode value = getValue(n, proxy.value(), nodeMap);
-            return lastLocationAccess.graph().add(new ValueProxyNode(value, proxy.proxyPoint(), PhiType.Value));
-        }
-        if (lastLocationAccess instanceof WriteNode) {
-            return ((WriteNode) lastLocationAccess).value();
-        }
-        if (lastLocationAccess instanceof PhiNode) {
-            PhiNode phi = (PhiNode) lastLocationAccess;
-            PhiNode newPhi = phi.graph().add(new PhiNode(n.kind(), phi.merge()));
-            nodeMap.set(lastLocationAccess, newPhi);
-            for (ValueNode value : phi.values()) {
-                newPhi.addInput(getValue(n, value, nodeMap));
-            }
-            newPhis.add(newPhi);
-            return newPhi;
-        }
-        throw GraalInternalError.shouldNotReachHere();
-    }
-}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/RemoveValueProxyPhase.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 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 com.oracle.graal.compiler.phases;
-
-import com.oracle.graal.nodes.*;
-
-public class RemoveValueProxyPhase extends Phase {
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        for (ValueProxyNode vpn : graph.getNodes(ValueProxyNode.class)) {
-            graph.replaceFloating(vpn, vpn.value());
-        }
-        for (LoopExitNode exit : graph.getNodes(LoopExitNode.class)) {
-            FrameState stateAfter = exit.stateAfter();
-            if (stateAfter != null) {
-                exit.setStateAfter(null);
-                if (stateAfter.usages().count() == 0) {
-                    stateAfter.safeDelete();
-                }
-            }
-        }
-    }
-}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/phases/TailDuplicationPhase.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,551 +0,0 @@
-/*
- * Copyright (c) 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 com.oracle.graal.compiler.phases;
-
-import java.util.*;
-
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.Graph.DuplicationReplacement;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.VirtualState.NodeClosure;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.nodes.util.*;
-
-/**
- * This class is a phase that looks for opportunities for tail duplication. The static method
- * {@link #tailDuplicate(MergeNode, TailDuplicationDecision, List)} can also be used to drive tail duplication from
- * other places, e.g., inlining.
- */
-public class TailDuplicationPhase extends Phase {
-
-    /*
-     * Various metrics on the circumstances in which tail duplication was/wasn't performed.
-     */
-    private static final DebugMetric metricDuplicationMonitors = Debug.metric("DuplicationMonitors");
-    private static final DebugMetric metricDuplicationEnd = Debug.metric("DuplicationEnd");
-    private static final DebugMetric metricDuplicationEndPerformed = Debug.metric("DuplicationEndPerformed");
-    private static final DebugMetric metricDuplicationOther = Debug.metric("DuplicationOther");
-    private static final DebugMetric metricDuplicationOtherPerformed = Debug.metric("DuplicationOtherPerformed");
-
-    /**
-     * This interface is used by tail duplication to let clients decide if tail duplication should be performed.
-     */
-    public interface TailDuplicationDecision {
-
-        /**
-         * Queries if tail duplication should be performed at the given merge. If this method returns true then the tail
-         * duplication will be performed, because all other checks have happened before.
-         *
-         * @param merge The merge at which tail duplication can be performed.
-         * @param fixedNodeCount The size of the set of fixed nodes that forms the base for the duplicated set of nodes.
-         * @return true if the tail duplication should be performed, false otherwise.
-         */
-        boolean doTransform(MergeNode merge, int fixedNodeCount);
-    }
-
-    /**
-     * A tail duplication decision closure that employs the default algorithm: Check if there are any phis on the merge
-     * whose stamps improve and that have usages within the duplicated set of fixed nodes.
-     */
-    public static final TailDuplicationDecision DEFAULT_DECISION = new TailDuplicationDecision() {
-
-        public boolean doTransform(MergeNode merge, int fixedNodeCount) {
-            if (fixedNodeCount < GraalOptions.TailDuplicationTrivialSize) {
-                return true;
-            }
-            HashSet<PhiNode> improvements = new HashSet<>();
-            for (PhiNode phi : merge.phis()) {
-                Stamp phiStamp = phi.stamp();
-                for (ValueNode input : phi.values()) {
-                    if (!input.stamp().equals(phiStamp)) {
-                        improvements.add(phi);
-                        break;
-                    }
-                }
-            }
-            if (improvements.isEmpty()) {
-                return false;
-            }
-            FixedNode current = merge;
-            int opportunities = 0;
-            while (current instanceof FixedWithNextNode) {
-                current = ((FixedWithNextNode) current).next();
-                for (PhiNode phi : improvements) {
-                    for (Node input : current.inputs()) {
-                        if (input == phi) {
-                            opportunities++;
-                        }
-                        if (input.inputs().contains(phi)) {
-                            opportunities++;
-                        }
-                    }
-                }
-            }
-            return opportunities > 0;
-        }
-    };
-
-    /**
-     * A tail duplication decision closure that always returns true.
-     */
-    public static final TailDuplicationDecision TRUE_DECISION = new TailDuplicationDecision() {
-
-        @Override
-        public boolean doTransform(MergeNode merge, int fixedNodeCount) {
-            return true;
-        }
-    };
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        // A snapshot is taken here, so that new MergeNode instances aren't considered for tail duplication.
-        for (MergeNode merge : graph.getNodes(MergeNode.class).snapshot()) {
-            if (!(merge instanceof LoopBeginNode) && merge.probability() >= GraalOptions.TailDuplicationProbability) {
-                tailDuplicate(merge, DEFAULT_DECISION, null);
-            }
-        }
-    }
-
-    /**
-     * This method attempts to duplicate the tail of the given merge. The merge must not be a {@link LoopBeginNode}. If
-     * the merge is eligible for duplication (at least one fixed node in its tail, no {@link MonitorEnterNode}/
-     * {@link MonitorExitNode}, non-null {@link MergeNode#stateAfter()}) then the decision callback is used to determine
-     * whether the tail duplication should actually be performed. If replacements is non-null, then this list of
-     * {@link PiNode}s is used to replace one value per merge end.
-     *
-     * @param merge The merge whose tail should be duplicated.
-     * @param decision A callback that can make the final decision if tail duplication should occur or not.
-     * @param replacements A list of {@link PiNode}s, or null. If this list is non-null then its size needs to match the
-     *            merge's end count. Each entry can either be null or a {@link PiNode}, and is used to replace
-     *            {@link PiNode#object()} with the {@link PiNode} in the duplicated branch that corresponds to the
-     *            entry.
-     */
-    public static void tailDuplicate(MergeNode merge, TailDuplicationDecision decision, List<PiNode> replacements) {
-        assert !(merge instanceof LoopBeginNode);
-        assert replacements == null || replacements.size() == merge.forwardEndCount();
-        FixedNode fixed = merge;
-        int fixedCount = 0;
-        boolean containsMonitor = false;
-        while (fixed instanceof FixedWithNextNode) {
-            if (fixed instanceof MonitorEnterNode || fixed instanceof MonitorExitNode) {
-                containsMonitor = true;
-            }
-            fixed = ((FixedWithNextNode) fixed).next();
-            fixedCount++;
-        }
-        if (containsMonitor) {
-            // cannot currently be handled
-            // TODO (ls) re-evaluate this limitation after changes to the lock representation and the LIR generator
-            metricDuplicationMonitors.increment();
-        } else if (fixedCount > 1) {
-            if (fixed instanceof EndNode && !(((EndNode) fixed).merge() instanceof LoopBeginNode)) {
-                metricDuplicationEnd.increment();
-                if (decision.doTransform(merge, fixedCount)) {
-                    metricDuplicationEndPerformed.increment();
-                    new DuplicationOperation(merge, replacements).duplicate();
-                }
-            } else if (merge.stateAfter() != null) {
-                metricDuplicationOther.increment();
-                if (decision.doTransform(merge, fixedCount)) {
-                    metricDuplicationOtherPerformed.increment();
-                    new DuplicationOperation(merge, replacements).duplicate();
-                }
-            }
-        }
-    }
-
-    /**
-     * This class encapsulates one tail duplication operation on a specific {@link MergeNode}.
-     */
-    private static class DuplicationOperation {
-
-        private final MergeNode merge;
-        private final StructuredGraph graph;
-
-        private final HashMap<ValueNode, PhiNode> bottomPhis = new HashMap<>();
-        private final List<PiNode> replacements;
-
-        /**
-         * Initializes the tail duplication operation without actually performing any work.
-         *
-         * @param merge The merge whose tail should be duplicated.
-         * @param replacements A list of replacement {@link PiNode}s, or null. If this is non-null, then the size of the
-         *            list needs to match the number of end nodes at the merge.
-         */
-        public DuplicationOperation(MergeNode merge, List<PiNode> replacements) {
-            this.merge = merge;
-            this.replacements = replacements;
-            this.graph = (StructuredGraph) merge.graph();
-        }
-
-        /**
-         * Performs the actual tail duplication:
-         * <ul>
-         * <li>Creates a new {@link ValueAnchorNode} at the beginning of the duplicated area, an transfers all
-         * dependencies from the merge to this anchor.</li>
-         * <li>Determines the set of fixed nodes to be duplicated.</li>
-         * <li>Creates the new merge at the bottom of the duplicated area.</li>
-         * <li>Determines the complete set of duplicated nodes.</li>
-         * <li>Performs the actual duplication.</li>
-         * </ul>
-         */
-        private void duplicate() {
-            Debug.log("tail duplication at merge %s in %s (prob %f)", merge, graph.method(), merge.probability());
-
-            ValueAnchorNode anchor = addValueAnchor();
-
-            // determine the fixed nodes that should be duplicated (currently: all nodes up until the first control
-            // split, end node, deopt or return.
-            ArrayList<FixedNode> fixedNodes = new ArrayList<>();
-            FixedNode fixed = merge.next();
-            FrameState stateAfter = merge.stateAfter();
-            while (fixed instanceof FixedWithNextNode) {
-                fixedNodes.add(fixed);
-                if (fixed instanceof StateSplit && ((StateSplit) fixed).stateAfter() != null) {
-                    stateAfter = ((StateSplit) fixed).stateAfter();
-                }
-                fixed = ((FixedWithNextNode) fixed).next();
-            }
-
-            EndNode endAfter = createNewMerge(fixed, stateAfter);
-            MergeNode mergeAfter = endAfter.merge();
-            fixedNodes.add(endAfter);
-            final HashSet<Node> duplicatedNodes = buildDuplicatedNodeSet(fixedNodes, stateAfter);
-            mergeAfter.clearEnds();
-            expandDuplicated(duplicatedNodes, mergeAfter);
-            retargetDependencies(duplicatedNodes, anchor);
-
-            List<EndNode> endSnapshot = merge.forwardEnds().snapshot();
-            List<PhiNode> phiSnapshot = merge.phis().snapshot();
-
-            int endIndex = 0;
-            for (final EndNode forwardEnd : merge.forwardEnds()) {
-                Map<Node, Node> duplicates;
-                if (replacements == null || replacements.get(endIndex) == null) {
-                    duplicates = graph.addDuplicates(duplicatedNodes, (DuplicationReplacement) null);
-                } else {
-                    HashMap<Node, Node> replace = new HashMap<>();
-                    replace.put(replacements.get(endIndex).object(), replacements.get(endIndex));
-                    duplicates = graph.addDuplicates(duplicatedNodes, replace);
-                }
-                for (Map.Entry<ValueNode, PhiNode> phi : bottomPhis.entrySet()) {
-                    phi.getValue().initializeValueAt(merge.forwardEndIndex(forwardEnd), (ValueNode) duplicates.get(phi.getKey()));
-                }
-                mergeAfter.addForwardEnd((EndNode) duplicates.get(endAfter));
-
-                // re-wire the duplicated ValueAnchorNode to the predecessor of the corresponding EndNode
-                FixedNode anchorDuplicate = (FixedNode) duplicates.get(anchor);
-                ((FixedWithNextNode) forwardEnd.predecessor()).setNext(anchorDuplicate);
-                // move dependencies on the ValueAnchorNode to the previous BeginNode
-                BeginNode prevBegin = BeginNode.prevBegin(anchorDuplicate);
-                anchorDuplicate.replaceAtUsages(prevBegin);
-
-                // re-wire the phi duplicates to the correct input
-                for (PhiNode phi : phiSnapshot) {
-                    PhiNode phiDuplicate = (PhiNode) duplicates.get(phi);
-                    for (Node usage : phiDuplicate.usages()) {
-                        if (usage instanceof ValueNode) {
-                            ((ValueNode) usage).dependencies().add(prevBegin);
-                        }
-                    }
-                    phiDuplicate.replaceAtUsages(phi.valueAt(forwardEnd));
-                    phiDuplicate.safeDelete();
-                }
-                endIndex++;
-            }
-            GraphUtil.killCFG(merge);
-            for (EndNode forwardEnd : endSnapshot) {
-                forwardEnd.safeDelete();
-            }
-            for (PhiNode phi : phiSnapshot) {
-                // these phis should go away, but they still need to be anchored to a merge to be valid...
-                if (phi.isAlive()) {
-                    phi.setMerge(mergeAfter);
-                }
-            }
-            Debug.dump(graph, "After tail duplication at %s", merge);
-        }
-
-        /**
-         * Inserts a new ValueAnchorNode after the merge and transfers all dependency-usages (not phis) to this
-         * ValueAnchorNode.
-         *
-         * @return The new {@link ValueAnchorNode} that was created.
-         */
-        private ValueAnchorNode addValueAnchor() {
-            ValueAnchorNode anchor = graph.add(new ValueAnchorNode());
-            graph.addAfterFixed(merge, anchor);
-            for (Node usage : merge.usages().snapshot()) {
-                if (usage instanceof PhiNode && ((PhiNode) usage).merge() == merge) {
-                    // nothing to do
-                } else {
-                    usage.replaceFirstInput(merge, anchor);
-                }
-            }
-            return anchor;
-        }
-
-        /**
-         * Given a set of fixed nodes, this method determines the set of fixed and floating nodes that needs to be
-         * duplicated, i.e., all nodes that due to data flow and other dependencies needs to be duplicated.
-         *
-         * @param fixedNodes The set of fixed nodes that should be duplicated.
-         * @param stateAfter The frame state of the merge that follows the set of fixed nodes. All {@link ValueNode}s
-         *            reachable from this state are considered to be reachable from within the duplicated set of nodes.
-         * @return The set of nodes that need to be duplicated.
-         */
-        private HashSet<Node> buildDuplicatedNodeSet(final ArrayList<FixedNode> fixedNodes, FrameState stateAfter) {
-            final NodeBitMap aboveBound = graph.createNodeBitMap();
-            final NodeBitMap belowBound = graph.createNodeBitMap();
-
-            final Deque<Node> worklist = new ArrayDeque<>();
-
-            // Build the set of nodes that have (transitive) usages within the duplicatedNodes.
-            // This is achieved by iterating all nodes that are reachable via inputs from the the fixed nodes.
-            aboveBound.markAll(fixedNodes);
-            worklist.addAll(fixedNodes);
-
-            // the phis at the original merge should always be duplicated
-            for (PhiNode phi : merge.phis()) {
-                aboveBound.mark(phi);
-                worklist.add(phi);
-            }
-
-            NodeClosure<Node> aboveClosure = new NodeClosure<Node>() {
-
-                @Override
-                public void apply(Node usage, Node node) {
-                    if (node instanceof PhiNode && !fixedNodes.contains(((PhiNode) node).merge())) {
-                        // stop iterating: phis belonging to outside merges are known to be outside.
-                    } else if (node instanceof FixedNode) {
-                        // stop iterating: fixed nodes within the given set are traversal roots anyway, and all other
-                        // fixed nodes are known to be outside.
-                    } else if (!aboveBound.isMarked(node)) {
-                        worklist.add(node);
-                        aboveBound.mark(node);
-                    }
-                }
-            };
-
-            if (stateAfter != null) {
-                stateAfter.applyToNonVirtual(aboveClosure);
-            }
-            while (!worklist.isEmpty()) {
-                Node current = worklist.remove();
-                for (Node input : current.inputs()) {
-                    aboveClosure.apply(current, input);
-                }
-            }
-
-            // Build the set of nodes that have (transitive) inputs within the duplicatedNodes.
-            // This is achieved by iterating all nodes that are reachable via usages from the fixed nodes.
-            belowBound.markAll(fixedNodes);
-            worklist.addAll(fixedNodes);
-
-            // the phis at the original merge should always be duplicated
-            for (PhiNode phi : merge.phis()) {
-                belowBound.mark(phi);
-                worklist.add(phi);
-            }
-
-            while (!worklist.isEmpty()) {
-                Node current = worklist.remove();
-                for (Node usage : current.usages()) {
-                    if (usage instanceof PhiNode && !fixedNodes.contains(((PhiNode) usage).merge())) {
-                        // stop iterating: phis belonging to outside merges are known to be outside.
-                    } else if (usage instanceof FixedNode) {
-                        // stop iterating: fixed nodes within the given set are traversal roots anyway, and all other
-                        // fixed nodes are known to be outside.
-                    } else if (!belowBound.isMarked(usage)) {
-                        worklist.add(usage);
-                        belowBound.mark(usage);
-                    }
-                }
-            }
-
-            // build the intersection
-            belowBound.intersect(aboveBound);
-            HashSet<Node> result = new HashSet<>();
-            for (Node node : belowBound) {
-                result.add(node);
-            }
-            return result;
-        }
-
-        /**
-         * Creates a new merge and end node construct at the end of the duplicated area. While it is useless in itself
-         * (merge with only one end) it simplifies the later duplication step.
-         *
-         * @param successor The successor of the duplicated set of nodes, i.e., the first node that should not be
-         *            duplicated.
-         * @param stateAfterMerge The frame state that should be used for the merge.
-         * @return The newly created end node.
-         */
-        private EndNode createNewMerge(FixedNode successor, FrameState stateAfterMerge) {
-            MergeNode newBottomMerge = graph.add(new MergeNode());
-            newBottomMerge.setProbability(successor.probability());
-            EndNode newBottomEnd = graph.add(new EndNode());
-            newBottomMerge.addForwardEnd(newBottomEnd);
-            newBottomMerge.setStateAfter(stateAfterMerge);
-            ((FixedWithNextNode) successor.predecessor()).setNext(newBottomEnd);
-            newBottomMerge.setNext(successor);
-            return newBottomEnd;
-        }
-
-        /**
-         * Expands the set of nodes to be duplicated by looking at a number of conditions:
-         * <ul>
-         * <li>{@link ValueNode}s that have usages on the outside need to be replaced with phis for the outside usages.</li>
-         * <li>Non-{@link ValueNode} nodes that have outside usages (frame states, virtual object states, ...) need to
-         * be cloned immediately for the outside usages.</li>
-         * <li>Nodes that have a {@link StampFactory#extension()} or {@link StampFactory#condition()} stamp need to be
-         * cloned immediately for the outside usages.</li>
-         * <li>Dependencies into the duplicated nodes will be replaced with dependencies on the merge.</li>
-         * <li>Outside non-{@link ValueNode}s with usages within the duplicated set of nodes need to also be duplicated.
-         * </li>
-         * <li>Outside {@link ValueNode}s with {@link StampFactory#extension()} or {@link StampFactory#condition()}
-         * stamps that have usages within the duplicated set of nodes need to also be duplicated.</li>
-         * </ul>
-         *
-         * @param duplicatedNodes The set of duplicated nodes that will be modified (expanded).
-         * @param newBottomMerge The merge that follows the duplicated set of nodes. It will be used for newly created
-         *            phis and to as a target for dependencies that pointed into the duplicated set of nodes.
-         */
-        private void expandDuplicated(HashSet<Node> duplicatedNodes, MergeNode newBottomMerge) {
-            Deque<Node> worklist = new ArrayDeque<>(duplicatedNodes);
-
-            while (!worklist.isEmpty()) {
-                Node duplicated = worklist.remove();
-                if (hasUsagesOutside(duplicated, duplicatedNodes)) {
-                    boolean cloneForOutsideUsages = false;
-                    if (duplicated instanceof ValueNode) {
-                        ValueNode node = (ValueNode) duplicated;
-                        if (node.stamp() == StampFactory.dependency()) {
-                            // re-route dependencies to the merge
-                            replaceUsagesOutside(node, newBottomMerge, duplicatedNodes);
-                            // TODO(ls) maybe introduce phis for dependencies
-                        } else if (node.stamp() == StampFactory.extension() || node.stamp() == StampFactory.condition()) {
-                            cloneForOutsideUsages = true;
-                        } else {
-                            // introduce a new phi
-                            PhiNode newPhi = bottomPhis.get(node);
-                            if (newPhi == null) {
-                                newPhi = graph.add(new PhiNode(node.kind(), newBottomMerge));
-                                bottomPhis.put(node, newPhi);
-                                newPhi.addInput(node);
-                            }
-                            replaceUsagesOutside(node, newPhi, duplicatedNodes);
-                        }
-                    } else {
-                        cloneForOutsideUsages = true;
-                    }
-                    if (cloneForOutsideUsages) {
-                        // clone the offending node to the outside
-                        Node newOutsideClone = duplicated.copyWithInputs();
-                        replaceUsagesOutside(duplicated, newOutsideClone, duplicatedNodes);
-                        // this might cause other nodes to have outside usages, we need to look at those as well
-                        for (Node input : newOutsideClone.inputs()) {
-                            if (duplicatedNodes.contains(input)) {
-                                worklist.add(input);
-                            }
-                        }
-                    }
-                }
-                // check if this node has an input that lies outside and cannot be shared
-                for (Node input : duplicated.inputs()) {
-                    if (!duplicatedNodes.contains(input)) {
-                        boolean duplicateInput = false;
-                        if (input instanceof VirtualState) {
-                            duplicateInput = true;
-                        } else if (input instanceof ValueNode) {
-                            Stamp inputStamp = ((ValueNode) input).stamp();
-                            if (inputStamp == StampFactory.extension() || inputStamp == StampFactory.condition()) {
-                                duplicateInput = true;
-                            }
-                        }
-                        if (duplicateInput) {
-                            duplicatedNodes.add(input);
-                            worklist.add(input);
-                        }
-                    }
-                }
-            }
-        }
-
-        /**
-         * Moves all depdendencies that point outside the duplicated area to the supplied value anchor node.
-         *
-         * @param duplicatedNodes The set of duplicated nodes.
-         * @param anchor The node that will be the new target for all dependencies that point outside the duplicated set of nodes.
-         */
-        private static void retargetDependencies(HashSet<Node> duplicatedNodes, ValueAnchorNode anchor) {
-            for (Node node : duplicatedNodes) {
-                if (node instanceof ValueNode) {
-                    NodeInputList<ValueNode> dependencies = ((ValueNode) node).dependencies();
-                    for (int i = 0; i < dependencies.size(); i++) {
-                        Node dependency = dependencies.get(i);
-                        if (dependency != null && !duplicatedNodes.contains(dependency)) {
-                            Debug.log("retargeting dependency %s to %s on %s", dependency, anchor, node);
-                            dependencies.set(i, anchor);
-                        }
-                    }
-                }
-            }
-        }
-
-        /**
-         * Checks if the given node has usages that are not within the given set of nodes.
-         *
-         * @param node The node whose usages are checked.
-         * @param nodeSet The set of nodes that are considered to be "within".
-         * @return true if the given node has usages on the outside, false otherwise.
-         */
-        private static boolean hasUsagesOutside(Node node, HashSet<Node> nodeSet) {
-            for (Node usage : node.usages()) {
-                if (!nodeSet.contains(usage)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        /**
-         * Replaces the given node with the given replacement at all usages that are not within the given set of nodes.
-         *
-         * @param node The node to be replaced at outside usages.
-         * @param replacement The node that replaced the given node at outside usages.
-         * @param nodeSet The set of nodes that are considered to be "within".
-         */
-        private static void replaceUsagesOutside(Node node, Node replacement, HashSet<Node> nodeSet) {
-            for (Node usage : node.usages().snapshot()) {
-                if (!nodeSet.contains(usage)) {
-                    usage.replaceFirstInput(node, replacement);
-                }
-            }
-        }
-    }
-}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/schedule/BlockClosure.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.schedule;
-
-import com.oracle.graal.lir.cfg.*;
-
-/**
- * The {@code BlockClosure} interface represents a closure for iterating over blocks.
- */
-public interface BlockClosure {
-    void apply(Block block);
-}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/schedule/SchedulePhase.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,399 +0,0 @@
-/*
- * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.schedule;
-
-import java.util.*;
-
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.phases.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.Node.Verbosity;
-import com.oracle.graal.lir.cfg.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.virtual.*;
-
-public class SchedulePhase extends Phase {
-    private ControlFlowGraph cfg;
-    private NodeMap<Block> earliestCache;
-
-    /**
-     * Map from blocks to the nodes in each block.
-     */
-    private BlockMap<List<ScheduledNode>> blockToNodesMap;
-
-    public SchedulePhase() {
-        super("Schedule");
-    }
-
-    @Override
-    protected void run(StructuredGraph graph) {
-        cfg = ControlFlowGraph.compute(graph, true, true, true, false);
-        earliestCache = graph.createNodeMap();
-        blockToNodesMap = new BlockMap<>(cfg);
-
-        assignBlockToNodes(graph);
-        sortNodesWithinBlocks(graph);
-    }
-
-    /**
-     * Sets {@link ScheduledNode#scheduledNext} on all scheduled nodes in all blocks using the scheduling built by @link {@link #run(StructuredGraph)}.
-     * This method should thus only be called when run has been successfully executed.
-     */
-    public void scheduleGraph() {
-        assert blockToNodesMap != null : "cannot set scheduledNext before run has been executed";
-        for (Block block : cfg.getBlocks()) {
-            List<ScheduledNode> nodeList = blockToNodesMap.get(block);
-            ScheduledNode last = null;
-            for (ScheduledNode node : nodeList) {
-                if (last != null) {
-                    last.setScheduledNext(node);
-                }
-                last = node;
-            }
-        }
-    }
-
-    public ControlFlowGraph getCFG() {
-        return cfg;
-    }
-
-    /**
-     * Gets the map from each block to the nodes in the block.
-     */
-    public BlockMap<List<ScheduledNode>> getBlockToNodesMap() {
-        return blockToNodesMap;
-    }
-
-    /**
-     * Gets the nodes in a given block.
-     */
-    public List<ScheduledNode> nodesFor(Block block) {
-        return blockToNodesMap.get(block);
-    }
-
-    private void assignBlockToNodes(StructuredGraph graph) {
-        for (Block block : cfg.getBlocks()) {
-            List<ScheduledNode> nodes = new ArrayList<>();
-            assert blockToNodesMap.get(block) == null;
-            blockToNodesMap.put(block, nodes);
-            for (FixedNode node : block.getNodes()) {
-                nodes.add(node);
-            }
-        }
-
-        for (Node n : graph.getNodes()) {
-            if (n instanceof ScheduledNode) {
-                assignBlockToNode((ScheduledNode) n);
-            }
-        }
-    }
-
-    /**
-     * Assigns a block to the given node. This method expects that PhiNodes and FixedNodes are already assigned to a block.
-     */
-    private void assignBlockToNode(ScheduledNode node) {
-        assert !node.isDeleted();
-
-        Block prevBlock = cfg.getNodeToBlock().get(node);
-        if (prevBlock != null) {
-            return;
-        }
-        // PhiNodes and FixedNodes should already have been placed in blocks by ControlFlowGraph.identifyBlocks
-        assert !(node instanceof PhiNode) : node;
-        assert !(node instanceof FixedNode) : node;
-        // if in CFG, schedule at the latest position possible in the outermost loop possible
-        Block latestBlock = latestBlock(node);
-        Block block;
-        if (latestBlock == null) {
-            block = earliestBlock(node);
-        } else if (GraalOptions.ScheduleOutOfLoops && !(node instanceof VirtualObjectNode)) {
-            Block earliestBlock = earliestBlock(node);
-            block = scheduleOutOfLoops(node, latestBlock, earliestBlock);
-            assert earliestBlock.dominates(block) : "Graph can not be scheduled : inconsistent for " + node + " (" + earliestBlock + " needs to dominate " + block + ")";
-        } else {
-            block = latestBlock;
-        }
-        cfg.getNodeToBlock().set(node, block);
-        blockToNodesMap.get(block).add(node);
-    }
-
-    /**
-     * Calculates the last block that the given node could be scheduled in, i.e., the common dominator of all usages.
-     * To do so all usages are also assigned to blocks.
-     */
-    private Block latestBlock(ScheduledNode node) {
-        CommonDominatorBlockClosure cdbc = new CommonDominatorBlockClosure(null);
-        for (Node succ : node.successors().nonNull()) {
-            assert cfg.getNodeToBlock().get(succ) != null;
-            cdbc.apply(cfg.getNodeToBlock().get(succ));
-        }
-        ensureScheduledUsages(node);
-        for (Node usage : node.usages()) {
-            blocksForUsage(node, usage, cdbc);
-        }
-        return cdbc.block;
-    }
-
-    /**
-     * A closure that will calculate the common dominator of all blocks passed to its {@link #apply(Block)} method.
-     */
-    private static class CommonDominatorBlockClosure implements BlockClosure {
-        public Block block;
-        public CommonDominatorBlockClosure(Block block) {
-            this.block = block;
-        }
-        @Override
-        public void apply(Block newBlock) {
-            this.block = getCommonDominator(this.block, newBlock);
-        }
-    }
-
-    /**
-     * Determines the earliest block in which the given node can be scheduled.
-     */
-    private Block earliestBlock(Node node) {
-        Block earliest = cfg.getNodeToBlock().get(node);
-        if (earliest != null) {
-            return earliest;
-        }
-        earliest = earliestCache.get(node);
-        if (earliest != null) {
-            return earliest;
-        }
-        /*
-         * All inputs must be in a dominating block, otherwise the graph cannot be scheduled. This implies that the
-         * inputs' blocks have a total ordering via their dominance relation. So in order to find the earliest block
-         * placement for this node we need to find the input block that is dominated by all other input blocks.
-         *
-         * While iterating over the inputs a set of dominator blocks of the current earliest placement is maintained.
-         * When the block of an input is not within this set, it becomes the current earliest placement and the list of
-         * dominator blocks is updated.
-         */
-        BitSet dominators = new BitSet(cfg.getBlocks().length);
-
-        assert node.predecessor() == null;
-        for (Node input : node.inputs().nonNull()) {
-            assert input instanceof ValueNode;
-            Block inputEarliest = earliestBlock(input);
-            if (!dominators.get(inputEarliest.getId())) {
-                earliest = inputEarliest;
-                do {
-                    dominators.set(inputEarliest.getId());
-                    inputEarliest = inputEarliest.getDominator();
-                } while(inputEarliest != null && !dominators.get(inputEarliest.getId()));
-            }
-        }
-        if (earliest == null) {
-            earliest = cfg.getStartBlock();
-        }
-        earliestCache.set(node, earliest);
-        return earliest;
-    }
-
-
-    private static Block scheduleOutOfLoops(Node n, Block latestBlock, Block earliest) {
-        assert latestBlock != null : "no latest : " + n;
-        Block cur = latestBlock;
-        Block result = latestBlock;
-        while (cur.getLoop() != null && cur != earliest && cur.getDominator() != null) {
-            Block dom = cur.getDominator();
-            if (dom.getLoopDepth() < result.getLoopDepth()) {
-                result = dom;
-            }
-            cur = dom;
-        }
-        return result;
-    }
-
-    /**
-     * Passes all blocks that a specific usage of a node is in to a given closure.
-     * This is more complex than just taking the usage's block because of of PhiNodes and FrameStates.
-     *
-     * @param node the node that needs to be scheduled
-     * @param usage the usage whose blocks need to be considered
-     * @param closure the closure that will be called for each block
-     */
-    private void blocksForUsage(ScheduledNode node, Node usage, BlockClosure closure) {
-        assert !(node instanceof PhiNode);
-
-        if (usage instanceof PhiNode) {
-            // An input to a PhiNode is used at the end of the predecessor block that corresponds to the PhiNode input.
-            // One PhiNode can use an input multiple times, the closure will be called for each usage.
-            PhiNode phi = (PhiNode) usage;
-            MergeNode merge = phi.merge();
-            Block mergeBlock = cfg.getNodeToBlock().get(merge);
-            assert mergeBlock != null : "no block for merge " + merge.toString(Verbosity.Id);
-            for (int i = 0; i < phi.valueCount(); ++i) {
-                if (phi.valueAt(i) == node) {
-                    if (mergeBlock.getPredecessors().size() <= i) {
-                        TTY.println(merge.toString());
-                        TTY.println(phi.toString());
-                        TTY.println(merge.cfgPredecessors().toString());
-                        TTY.println(mergeBlock.getPredecessors().toString());
-                        TTY.println(phi.inputs().toString());
-                        TTY.println("value count: " + phi.valueCount());
-                    }
-                    closure.apply(mergeBlock.getPredecessors().get(i));
-                }
-            }
-        } else if (usage instanceof VirtualState) {
-            // The following logic does not work if node is a PhiNode, but this method is never called for PhiNodes.
-            for (Node unscheduledUsage : usage.usages()) {
-                if (unscheduledUsage instanceof VirtualState) {
-                    // If a FrameState is an outer FrameState this method behaves as if the inner FrameState was the actual usage, by recursing.
-                    blocksForUsage(node, unscheduledUsage, closure);
-                } else if (unscheduledUsage instanceof MergeNode) {
-                    // Only FrameStates can be connected to MergeNodes.
-                    assert usage instanceof FrameState;
-                    // If a FrameState belongs to a MergeNode then it's inputs will be placed at the common dominator of all EndNodes.
-                    for (Node pred : unscheduledUsage.cfgPredecessors()) {
-                        closure.apply(cfg.getNodeToBlock().get(pred));
-                    }
-                } else {
-                    // For the time being, only FrameStates can be connected to StateSplits.
-                    assert usage instanceof FrameState;
-                    assert unscheduledUsage instanceof StateSplit;
-                    // Otherwise: Put the input into the same block as the usage.
-                    assignBlockToNode((ScheduledNode) unscheduledUsage);
-                    closure.apply(cfg.getNodeToBlock().get(unscheduledUsage));
-                }
-            }
-        } else {
-            // All other types of usages: Put the input into the same block as the usage.
-            assignBlockToNode((ScheduledNode) usage);
-            closure.apply(cfg.getNodeToBlock().get(usage));
-        }
-    }
-
-    private void ensureScheduledUsages(Node node) {
-        for (Node usage : node.usages().filter(ScheduledNode.class)) {
-            assignBlockToNode((ScheduledNode) usage);
-        }
-        // now true usages are ready
-    }
-
-    private static Block getCommonDominator(Block a, Block b) {
-        if (a == null) {
-            return b;
-        }
-        if (b == null) {
-            return a;
-        }
-        return ControlFlowGraph.commonDominator(a, b);
-    }
-
-    private void sortNodesWithinBlocks(StructuredGraph graph) {
-        NodeBitMap visited = graph.createNodeBitMap();
-        for (Block b : cfg.getBlocks()) {
-            sortNodesWithinBlock(b, visited);
-        }
-    }
-
-    /**
-     * Sorts the nodes within a block by adding the nodes to a list in a post-order iteration over all inputs.
-     * This means that a node is added to the list after all its inputs have been processed.
-     */
-    private void sortNodesWithinBlock(Block b, NodeBitMap visited) {
-        List<ScheduledNode> instructions = blockToNodesMap.get(b);
-        List<ScheduledNode> sortedInstructions = new ArrayList<>(instructions.size() + 2);
-
-        assert !visited.isMarked(b.getBeginNode()) && cfg.blockFor(b.getBeginNode()) == b;
-        assert !visited.isMarked(b.getEndNode()) && cfg.blockFor(b.getEndNode()) == b;
-
-        for (ScheduledNode i : instructions) {
-            addToSorting(b, i, sortedInstructions, visited);
-        }
-
-        // Make sure that last node gets really last (i.e. when a frame state successor hangs off it).
-        Node lastSorted = sortedInstructions.get(sortedInstructions.size() - 1);
-        if (lastSorted != b.getEndNode()) {
-            int idx = sortedInstructions.indexOf(b.getEndNode());
-            boolean canNotMove = false;
-            for (int i = idx + 1; i < sortedInstructions.size(); i++) {
-                if (sortedInstructions.get(i).inputs().contains(b.getEndNode())) {
-                    canNotMove = true;
-                    break;
-                }
-            }
-            if (canNotMove) {
-                if (b.getEndNode() instanceof ControlSplitNode) {
-                    throw new GraalInternalError("Schedule is not possible : needs to move a node after the last node of the block which can not be move").
-                    addContext(lastSorted).
-                    addContext(b.getEndNode());
-                }
-
-                //b.setLastNode(lastSorted);
-            } else {
-                sortedInstructions.remove(b.getEndNode());
-                sortedInstructions.add(b.getEndNode());
-            }
-        }
-        blockToNodesMap.put(b, sortedInstructions);
-    }
-
-    private void addUnscheduledToSorting(Block b, VirtualState state, List<ScheduledNode> sortedInstructions, NodeBitMap visited) {
-        if (state != null) {
-            // UnscheduledNodes should never be marked as visited.
-            assert !visited.isMarked(state);
-
-            for (Node input : state.inputs()) {
-                if (input instanceof VirtualState) {
-                    addUnscheduledToSorting(b, (VirtualState) input, sortedInstructions, visited);
-                } else {
-                    addToSorting(b, (ScheduledNode) input, sortedInstructions, visited);
-                }
-            }
-        }
-    }
-
-    private void addToSorting(Block b, ScheduledNode i, List<ScheduledNode> sortedInstructions, NodeBitMap visited) {
-        if (i == null || visited.isMarked(i) || cfg.getNodeToBlock().get(i) != b || i instanceof PhiNode || i instanceof LocalNode) {
-            return;
-        }
-
-        FrameState state = null;
-        WriteNode write = null;
-        for (Node input : i.inputs()) {
-            if (input instanceof WriteNode && !visited.isMarked(input) && cfg.getNodeToBlock().get(input) == b) {
-                assert write == null;
-                write = (WriteNode) input;
-            } else if (input instanceof FrameState) {
-                assert state == null;
-                state = (FrameState) input;
-            } else {
-                addToSorting(b, (ScheduledNode) input, sortedInstructions, visited);
-            }
-        }
-
-        addToSorting(b, (ScheduledNode) i.predecessor(), sortedInstructions, visited);
-        visited.mark(i);
-        addUnscheduledToSorting(b, state, sortedInstructions, visited);
-        assert write == null || !visited.isMarked(write);
-        addToSorting(b, write, sortedInstructions, visited);
-
-        // Now predecessors and inputs are scheduled => we can add this node.
-        sortedInstructions.add(i);
-    }
-}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/util/ArrayMap.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.util;
-
-/**
- * The {@code ArrayMap} class implements an efficient one-level map which is implemented
- * as an array. Note that because of the one-level array inside, this data structure performs best
- * when the range of integer keys is small and densely used. Note that the implementation can
- * handle arbitrary intervals, including negative numbers, up to intervals of size 2^31 - 1.
- */
-public class ArrayMap<T> {
-
-    private static final int INITIAL_SIZE = 5; // how big the initial array should be
-    private static final int EXTRA = 2; // how far on the left or right of a new element to grow
-
-    Object[] map;
-    int low;
-
-    /**
-     * Constructs a new {@code ArrayMap} with no initial assumptions.
-     */
-    public ArrayMap() {
-    }
-
-    /**
-     * Constructs a new {@code ArrayMap} that initially covers the specified interval.
-     * Note that this map will automatically expand if necessary later.
-     * @param low the low index, inclusive
-     * @param high the high index, exclusive
-     */
-    public ArrayMap(int low, int high) {
-        this.low = low;
-        this.map = new Object[high - low + 1];
-    }
-
-    /**
-     * Puts a new value in the map at the specified index.
-     * @param i the index at which to store the value
-     * @param value the value to store at the specified index
-     */
-    public void put(int i, T value) {
-        int index = i - low;
-        if (map == null) {
-            // no map yet
-            map = new Object[INITIAL_SIZE];
-            low = index - 2;
-            map[INITIAL_SIZE / 2] = value;
-        } else if (index < 0) {
-            // grow backwards
-            growBackward(i, value);
-        } else if (index >= map.length) {
-            // grow forwards
-            growForward(i, value);
-        } else {
-            // no growth necessary
-            map[index] = value;
-        }
-    }
-
-    /**
-     * Gets the value at the specified index in the map.
-     * @param i the index
-     * @return the value at the specified index; {@code null} if there is no value at the specified index,
-     * or if the index is out of the currently stored range
-     */
-    public T get(int i) {
-        int index = i - low;
-        if (map == null || index < 0 || index >= map.length) {
-            return null;
-        }
-        Class<T> type = null;
-        return Util.uncheckedCast(type, map[index]);
-    }
-
-    public int length() {
-        return map.length;
-    }
-
-    private void growBackward(int i, T value) {
-        int nlow = i - EXTRA;
-        Object[] nmap = new Object[low - nlow + map.length];
-        System.arraycopy(map, 0, nmap, low - nlow, map.length);
-        map = nmap;
-        low = nlow;
-        map[i - low] = value;
-    }
-
-    private void growForward(int i, T value) {
-        int nlen = i - low + 1 + EXTRA;
-        Object[] nmap = new Object[nlen];
-        System.arraycopy(map, 0, nmap, 0, map.length);
-        map = nmap;
-        map[i - low] = value;
-    }
-}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/util/BitMap2D.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.util;
-
-import java.util.*;
-
-/**
- * This class implements a two-dimensional bitmap.
- */
-public final class BitMap2D {
-
-    private BitSet map;
-    private final int bitsPerSlot;
-
-    private int bitIndex(int slotIndex, int bitWithinSlotIndex)  {
-      return slotIndex * bitsPerSlot + bitWithinSlotIndex;
-    }
-
-    private boolean verifyBitWithinSlotIndex(int index)  {
-      assert index < bitsPerSlot : "index " + index + " is out of bounds " + bitsPerSlot;
-      return true;
-    }
-
-    public BitMap2D(int sizeInSlots, int bitsPerSlot) {
-        map = new BitSet(sizeInSlots * bitsPerSlot);
-        this.bitsPerSlot = bitsPerSlot;
-    }
-
-    public int sizeInBits() {
-      return map.size();
-    }
-
-    // Returns number of full slots that have been allocated
-    public int sizeInSlots() {
-      return map.size() / bitsPerSlot;
-    }
-
-    public boolean isValidIndex(int slotIndex, int bitWithinSlotIndex) {
-      assert verifyBitWithinSlotIndex(bitWithinSlotIndex);
-      return (bitIndex(slotIndex, bitWithinSlotIndex) < sizeInBits());
-    }
-
-    public boolean at(int slotIndex, int bitWithinSlotIndex)  {
-      assert verifyBitWithinSlotIndex(bitWithinSlotIndex);
-      return map.get(bitIndex(slotIndex, bitWithinSlotIndex));
-    }
-
-    public void setBit(int slotIndex, int bitWithinSlotIndex) {
-      assert verifyBitWithinSlotIndex(bitWithinSlotIndex);
-      map.set(bitIndex(slotIndex, bitWithinSlotIndex));
-    }
-
-    public void clearBit(int slotIndex, int bitWithinSlotIndex) {
-      assert verifyBitWithinSlotIndex(bitWithinSlotIndex);
-      map.clear(bitIndex(slotIndex, bitWithinSlotIndex));
-    }
-
-    public void atPutGrow(int slotIndex, int bitWithinSlotIndex, boolean value) {
-       int size = sizeInSlots();
-       if (size <= slotIndex) {
-           while (size <= slotIndex) {
-               size *= 2;
-           }
-           BitSet newBitMap = new BitSet(size * bitsPerSlot);
-           newBitMap.or(map);
-           map = newBitMap;
-       }
-
-       if (value) {
-           setBit(slotIndex, bitWithinSlotIndex);
-       } else {
-           clearBit(slotIndex, bitWithinSlotIndex);
-       }
-    }
-
-    public void clear() {
-        map.clear();
-    }
-}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/util/BlockWorkList.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,122 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.util;
-
-import com.oracle.graal.nodes.*;
-
-/**
- * This class implements a worklist for dealing with blocks. The worklist can
- * operate either as a stack (i.e. first-in / last-out), or as a sorted list,
- * where blocks can be sorted by a supplied number. The latter usage lends itself
- * naturally to iterative dataflow analysis problems.
- */
-public class BlockWorkList {
-    MergeNode[] workList;
-    int[] workListNumbers;
-    int workListIndex;
-
-    /**
-     * Adds a block to this list in an unsorted fashion, like a stack.
-     * @param block the block to add
-     */
-    public void add(MergeNode block) {
-        if (workList == null) {
-            // worklist not allocated yet
-            allocate();
-        } else if (workListIndex == workList.length) {
-            // need to grow the worklist
-            grow();
-        }
-        // put the block at the end of the array
-        workList[workListIndex++] = block;
-    }
-
-    /**
-     * Adds a block to this list, sorted by the supplied number. The block
-     * with the lowest number is returned upon subsequent removes.
-     * @param block the block to add
-     * @param number the number used to sort the block
-     */
-    public void addSorted(MergeNode block, int number) {
-        if (workList == null) {
-            // worklist not allocated yet
-            allocate();
-        } else if (workListIndex == workList.length) {
-            // need to grow the worklist
-            grow();
-        }
-        // put the block at the end of the array
-        workList[workListIndex] = block;
-        workListNumbers[workListIndex] = number;
-        workListIndex++;
-        int i = workListIndex - 2;
-        // push block towards the beginning of the array
-        for (; i >= 0; i--) {
-            int n = workListNumbers[i];
-            if (n >= number) {
-                break; // already in the right position
-            }
-            workList[i + 1] = workList[i]; // bubble b down by one
-            workList[i] = block;           // and overwrite its place with block
-            workListNumbers[i + 1] = n;    // bubble n down by one
-            workListNumbers[i] = number;   // and overwrite its place with number
-        }
-    }
-
-    /**
-     * Removes the next block from this work list. If the blocks have been added
-     * in a sorted order, then the block with the lowest number is returned. Otherwise,
-     * the last block added is returned.
-     * @return the next block in the list
-     */
-    public MergeNode removeFromWorkList() {
-        if (workListIndex != 0) {
-            return workList[--workListIndex];
-        }
-        return null;
-    }
-
-    /**
-     * Checks whether the list is empty.
-     * @return {@code true} if this list is empty
-     */
-    public boolean isEmpty() {
-        return workListIndex == 0;
-    }
-
-    private void allocate() {
-        workList = new MergeNode[5];
-        workListNumbers = new int[5];
-    }
-
-    private void grow() {
-        int prevLength = workList.length;
-        MergeNode[] nworkList = new MergeNode[prevLength * 3];
-        System.arraycopy(workList, 0, nworkList, 0, prevLength);
-        workList = nworkList;
-
-        int[] nworkListNumbers = new int[prevLength * 3];
-        System.arraycopy(workListNumbers, 0, nworkListNumbers, 0, prevLength);
-        workListNumbers = nworkListNumbers;
-    }
-}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/util/GraphOrder.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,141 +0,0 @@
-/*
- * 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 com.oracle.graal.compiler.util;
-
-import java.util.*;
-
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-
-public class GraphOrder implements Iterable<Node> {
-
-    private final ArrayList<Node> nodes = new ArrayList<>();
-
-    private GraphOrder() {
-    }
-
-    public GraphOrder(Graph graph) {
-        NodeBitMap visited = graph.createNodeBitMap();
-
-        for (ReturnNode node : graph.getNodes(ReturnNode.class)) {
-            visitForward(visited, node);
-        }
-        for (UnwindNode node : graph.getNodes(UnwindNode.class)) {
-            visitForward(visited, node);
-        }
-        for (DeoptimizeNode node : graph.getNodes(DeoptimizeNode.class)) {
-            visitForward(visited, node);
-        }
-    }
-
-    public static GraphOrder forwardGraph(Graph graph) {
-        GraphOrder result = new GraphOrder();
-
-        NodeBitMap visited = graph.createNodeBitMap();
-
-        for (ReturnNode node : graph.getNodes(ReturnNode.class)) {
-            result.visitForward(visited, node);
-        }
-        for (UnwindNode node : graph.getNodes(UnwindNode.class)) {
-            result.visitForward(visited, node);
-        }
-        for (DeoptimizeNode node : graph.getNodes(DeoptimizeNode.class)) {
-            result.visitForward(visited, node);
-        }
-        return result;
-    }
-
-    public static GraphOrder backwardGraph(Graph graph) {
-        GraphOrder result = new GraphOrder();
-
-        NodeBitMap visited = graph.createNodeBitMap();
-
-        for (Node node : forwardGraph(graph)) {
-            result.visitBackward(visited, node);
-        }
-        return result;
-    }
-
-    private void visitForward(NodeBitMap visited, Node node) {
-        if (node != null && !visited.isMarked(node)) {
-            visited.mark(node);
-            if (node.predecessor() != null) {
-                visitForward(visited, node.predecessor());
-            }
-            if (node instanceof MergeNode) {
-                // make sure that the cfg predecessors of a MergeNode are processed first
-                MergeNode merge = (MergeNode) node;
-                for (int i = 0; i < merge.forwardEndCount(); i++) {
-                    visitForward(visited, merge.forwardEndAt(i));
-                }
-            }
-            for (Node input : node.inputs()) {
-                visitForward(visited, input);
-            }
-            nodes.add(node);
-        }
-    }
-
-    private void visitBackward(NodeBitMap visited, Node node) {
-        if (node != null && !visited.isMarked(node)) {
-            visited.mark(node);
-            for (Node successor : node.successors()) {
-                visitBackward(visited, successor);
-            }
-            for (Node usage : node.usages()) {
-                visitBackward(visited, usage);
-            }
-            nodes.add(node);
-        }
-    }
-
-    @Override
-    public Iterator<Node> iterator() {
-        return new Iterator<Node>() {
-
-            private int pos = 0;
-
-            private void removeDeleted() {
-                while (pos < nodes.size() && nodes.get(pos).isDeleted()) {
-                    pos++;
-                }
-            }
-
-            @Override
-            public boolean hasNext() {
-                removeDeleted();
-                return pos < nodes.size();
-            }
-
-            @Override
-            public Node next() {
-                return nodes.get(pos++);
-            }
-
-            @Override
-            public void remove() {
-                throw new UnsupportedOperationException();
-            }
-        };
-    }
-}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/util/InliningUtil.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,960 +0,0 @@
-/*
- * Copyright (c) 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 com.oracle.graal.compiler.util;
-
-import java.lang.reflect.*;
-import java.util.*;
-import java.util.concurrent.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.JavaType.Representation;
-import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType;
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.phases.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.FrameState.InliningIdentifier;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.nodes.util.*;
-
-public class InliningUtil {
-
-    private static final DebugMetric metricInliningTailDuplication = Debug.metric("InliningTailDuplication");
-
-    public interface InliningCallback {
-        StructuredGraph buildGraph(ResolvedJavaMethod method);
-        double inliningWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke);
-        void recordMethodContentsAssumption(ResolvedJavaMethod method);
-        void recordConcreteMethodAssumption(ResolvedJavaMethod method, ResolvedJavaType context, ResolvedJavaMethod impl);
-    }
-
-    public static String methodName(ResolvedJavaMethod method, Invoke invoke) {
-        if (!Debug.isLogEnabled()) {
-            return null;
-        } else if (invoke != null && invoke.stateAfter() != null) {
-            return methodName(invoke.stateAfter(), invoke.bci()) + ": " + MetaUtil.format("%H.%n(%p):%r", method) + " (" + method.codeSize() + " bytes)";
-        } else {
-            return MetaUtil.format("%H.%n(%p):%r", method) + " (" + method.codeSize() + " bytes)";
-        }
-    }
-
-    public static String methodName(InlineInfo info) {
-        if (!Debug.isLogEnabled()) {
-            return null;
-        } else if (info.invoke != null && info.invoke.stateAfter() != null) {
-            return methodName(info.invoke.stateAfter(), info.invoke.bci()) + ": " + info.toString();
-        } else {
-            return info.toString();
-        }
-    }
-
-    private static String methodName(FrameState frameState, int bci) {
-        StringBuilder sb = new StringBuilder();
-        if (frameState.outerFrameState() != null) {
-            sb.append(methodName(frameState.outerFrameState(), frameState.outerFrameState().bci));
-            sb.append("->");
-        }
-        sb.append(MetaUtil.format("%h.%n", frameState.method()));
-        sb.append("@").append(bci);
-        return sb.toString();
-    }
-
-    /**
-     * Represents an opportunity for inlining at the given invoke, with the given weight and level.
-     * The weight is the amortized weight of the additional code - so smaller is better.
-     * The level is the number of nested inlinings that lead to this invoke.
-     */
-    public abstract static class InlineInfo implements Comparable<InlineInfo> {
-        public final Invoke invoke;
-        public final double weight;
-        public final int level;
-
-        public InlineInfo(Invoke invoke, double weight, int level) {
-            this.invoke = invoke;
-            this.weight = weight;
-            this.level = level;
-        }
-
-        public abstract int compiledCodeSize();
-
-        @Override
-        public int compareTo(InlineInfo o) {
-            return (weight < o.weight) ? -1 : (weight > o.weight) ? 1 : 0;
-        }
-
-        protected static StructuredGraph getGraph(final ResolvedJavaMethod concrete, final InliningCallback callback) {
-            return Debug.scope("GetInliningGraph", concrete, new Callable<StructuredGraph>() {
-                @Override
-                public StructuredGraph call() throws Exception {
-                    return callback.buildGraph(concrete);
-                }
-            });
-        }
-
-        public abstract boolean canDeopt();
-
-        /**
-         * Performs the inlining described by this object and returns the node that represents the return value of the
-         * inlined method (or null for void methods and methods that have no non-exceptional exit).
-         *
-         * @param graph
-         * @param runtime
-         * @param callback
-         */
-        public abstract void inline(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback);
-    }
-
-    /**
-     * Represents an inlining opportunity where the compiler can statically determine a monomorphic target method and
-     * therefore is able to determine the called method exactly.
-     */
-    private static class ExactInlineInfo extends InlineInfo {
-        public final ResolvedJavaMethod concrete;
-
-        public ExactInlineInfo(Invoke invoke, double weight, int level, ResolvedJavaMethod concrete) {
-            super(invoke, weight, level);
-            this.concrete = concrete;
-        }
-
-        @Override
-        public void inline(StructuredGraph compilerGraph, GraalCodeCacheProvider runtime, final InliningCallback callback) {
-            StructuredGraph graph = getGraph(concrete, callback);
-            assert !IntrinsificationPhase.canIntrinsify(invoke, concrete, runtime);
-            callback.recordMethodContentsAssumption(concrete);
-            InliningUtil.inline(invoke, graph, true);
-        }
-
-        @Override
-        public int compiledCodeSize() {
-            return concrete.compiledCodeSize();
-        }
-
-        @Override
-        public String toString() {
-            return "exact " + MetaUtil.format("%H.%n(%p):%r", concrete);
-        }
-
-        @Override
-        public boolean canDeopt() {
-            return false;
-        }
-    }
-
-    /**
-     * Represents an inlining opportunity for which profiling information suggests a monomorphic receiver, but for which
-     * the receiver type cannot be proven. A type check guard will be generated if this inlining is performed.
-     */
-    private static class TypeGuardInlineInfo extends InlineInfo {
-        public final ResolvedJavaMethod concrete;
-        public final ResolvedJavaType type;
-
-        public TypeGuardInlineInfo(Invoke invoke, double weight, int level, ResolvedJavaMethod concrete, ResolvedJavaType type) {
-            super(invoke, weight, level);
-            this.concrete = concrete;
-            this.type = type;
-        }
-
-        @Override
-        public int compiledCodeSize() {
-            return concrete.compiledCodeSize();
-        }
-
-        @Override
-        public void inline(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback) {
-            // receiver null check must be before the type check
-            InliningUtil.receiverNullCheck(invoke);
-            ValueNode receiver = invoke.methodCallTarget().receiver();
-            LoadHubNode receiverHub = graph.add(new LoadHubNode(receiver));
-            ConstantNode typeHub = ConstantNode.forConstant(type.getEncoding(Representation.ObjectHub), runtime, graph);
-            ObjectEqualsNode typeCheck = graph.unique(new ObjectEqualsNode(receiverHub, typeHub));
-            FixedGuardNode guard = graph.add(new FixedGuardNode(typeCheck, DeoptimizationReason.TypeCheckedInliningViolated, DeoptimizationAction.InvalidateReprofile, invoke.leafGraphId()));
-            ValueAnchorNode anchor = graph.add(new ValueAnchorNode());
-            assert invoke.predecessor() != null;
-
-            ValueNode anchoredReceiver = createAnchoredReceiver(graph, anchor, type, receiver, true);
-            invoke.callTarget().replaceFirstInput(receiver, anchoredReceiver);
-
-            graph.addBeforeFixed(invoke.node(), receiverHub);
-            graph.addBeforeFixed(invoke.node(), guard);
-            graph.addBeforeFixed(invoke.node(), anchor);
-
-            StructuredGraph calleeGraph = getGraph(concrete, callback);
-            assert !IntrinsificationPhase.canIntrinsify(invoke, concrete, runtime);
-            callback.recordMethodContentsAssumption(concrete);
-            InliningUtil.inline(invoke, calleeGraph, false);
-        }
-
-        @Override
-        public String toString() {
-            return "type-checked " + MetaUtil.format("%H.%n(%p):%r", concrete);
-        }
-
-        @Override
-        public boolean canDeopt() {
-            return true;
-        }
-    }
-
-    /**
-     * Polymorphic inlining of m methods with n type checks (n >= m) in case that the profiling information suggests a reasonable
-     * amounts of different receiver types and different methods. If an unknown type is encountered a deoptimization is triggered.
-     */
-    private static class MultiTypeGuardInlineInfo extends InlineInfo {
-        public final List<ResolvedJavaMethod> concretes;
-        public final ProfiledType[] ptypes;
-        public final int[] typesToConcretes;
-        public final double notRecordedTypeProbability;
-
-        public MultiTypeGuardInlineInfo(Invoke invoke, double weight, int level, List<ResolvedJavaMethod> concretes, ProfiledType[] ptypes,
-                        int[] typesToConcretes, double notRecordedTypeProbability) {
-            super(invoke, weight, level);
-            assert concretes.size() > 0 && concretes.size() <= ptypes.length : "must have at least one method but no more than types methods";
-            assert ptypes.length == typesToConcretes.length : "array lengths must match";
-
-            this.concretes = concretes;
-            this.ptypes = ptypes;
-            this.typesToConcretes = typesToConcretes;
-            this.notRecordedTypeProbability = notRecordedTypeProbability;
-        }
-
-        @Override
-        public int compiledCodeSize() {
-            int result = 0;
-            for (ResolvedJavaMethod m: concretes) {
-                result += m.compiledCodeSize();
-            }
-            return result;
-        }
-
-        @Override
-        public void inline(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback) {
-            int numberOfMethods = concretes.size();
-            boolean hasReturnValue = invoke.node().kind() != Kind.Void;
-
-            // receiver null check must be the first node
-            InliningUtil.receiverNullCheck(invoke);
-            if (numberOfMethods > 1 || shouldFallbackToInvoke()) {
-                inlineMultipleMethods(graph, runtime, callback, numberOfMethods, hasReturnValue);
-            } else {
-                inlineSingleMethod(graph, runtime, callback);
-            }
-        }
-
-        private boolean shouldFallbackToInvoke() {
-            return notRecordedTypeProbability > 0;
-        }
-
-        private void inlineMultipleMethods(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback, int numberOfMethods, boolean hasReturnValue) {
-            FixedNode continuation = invoke.next();
-
-            ValueNode originalReceiver = invoke.methodCallTarget().receiver();
-            // setup merge and phi nodes for results and exceptions
-            MergeNode returnMerge = graph.add(new MergeNode());
-            returnMerge.setProbability(invoke.probability());
-            returnMerge.setStateAfter(invoke.stateAfter().duplicate(invoke.stateAfter().bci));
-
-            PhiNode returnValuePhi = null;
-            if (hasReturnValue) {
-                returnValuePhi = graph.unique(new PhiNode(invoke.node().kind(), returnMerge));
-            }
-
-            MergeNode exceptionMerge = null;
-            PhiNode exceptionObjectPhi = null;
-            if (invoke instanceof InvokeWithExceptionNode) {
-                InvokeWithExceptionNode invokeWithException = (InvokeWithExceptionNode) invoke;
-                DispatchBeginNode exceptionEdge = invokeWithException.exceptionEdge();
-                ExceptionObjectNode exceptionObject = (ExceptionObjectNode) exceptionEdge.next();
-
-                exceptionMerge = graph.add(new MergeNode());
-                exceptionMerge.setProbability(exceptionEdge.probability());
-
-                FixedNode exceptionSux = exceptionObject.next();
-                graph.addBeforeFixed(exceptionSux, exceptionMerge);
-                exceptionObjectPhi = graph.unique(new PhiNode(Kind.Object, exceptionMerge));
-                exceptionMerge.setStateAfter(exceptionEdge.stateAfter().duplicateModified(invoke.stateAfter().bci, true, Kind.Void, exceptionObjectPhi));
-            }
-
-            // create one separate block for each invoked method
-            BeginNode[] calleeEntryNodes = new BeginNode[numberOfMethods];
-            for (int i = 0; i < numberOfMethods; i++) {
-                int predecessors = 0;
-                double probability = 0;
-                for (int j = 0; j < typesToConcretes.length; j++) {
-                    if (typesToConcretes[j] == i) {
-                        predecessors++;
-                        probability += ptypes[j].probability;
-                    }
-                }
-
-                calleeEntryNodes[i] = createInvocationBlock(graph, invoke, returnMerge, returnValuePhi, exceptionMerge, exceptionObjectPhi, predecessors, invoke.probability() * probability, true);
-            }
-
-            // create the successor for an unknown type
-            FixedNode unknownTypeNode;
-            if (shouldFallbackToInvoke()) {
-                unknownTypeNode = createInvocationBlock(graph, invoke, returnMerge, returnValuePhi, exceptionMerge, exceptionObjectPhi, 1, notRecordedTypeProbability, false);
-            } else {
-                unknownTypeNode = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TypeCheckedInliningViolated, invoke.leafGraphId()));
-            }
-
-            // replace the invoke exception edge
-            if (invoke instanceof InvokeWithExceptionNode) {
-                InvokeWithExceptionNode invokeWithExceptionNode = (InvokeWithExceptionNode) invoke;
-                BeginNode exceptionEdge = invokeWithExceptionNode.exceptionEdge();
-                ExceptionObjectNode exceptionObject = (ExceptionObjectNode) exceptionEdge.next();
-                exceptionObject.replaceAtUsages(exceptionObjectPhi);
-                exceptionObject.setNext(null);
-                GraphUtil.killCFG(invokeWithExceptionNode.exceptionEdge());
-            }
-
-            // replace the invoke with a switch on the type of the actual receiver
-            LoadHubNode receiverHub = graph.add(new LoadHubNode(invoke.methodCallTarget().receiver()));
-            graph.addBeforeFixed(invoke.node(), receiverHub);
-            FixedNode dispatchOnType = createDispatchOnType(graph, receiverHub, calleeEntryNodes, unknownTypeNode);
-
-            assert invoke.next() == continuation;
-            invoke.setNext(null);
-            returnMerge.setNext(continuation);
-            invoke.node().replaceAtUsages(returnValuePhi);
-            invoke.node().replaceAndDelete(dispatchOnType);
-
-            ArrayList<PiNode> replacements = new ArrayList<>();
-
-            // do the actual inlining for every invoke
-            for (int i = 0; i < calleeEntryNodes.length; i++) {
-                BeginNode node = calleeEntryNodes[i];
-                Invoke invokeForInlining = (Invoke) node.next();
-
-                ResolvedJavaType commonType = getLeastCommonType(i);
-                ValueNode receiver = invokeForInlining.methodCallTarget().receiver();
-                boolean exact = getTypeCount(i) == 1;
-                PiNode anchoredReceiver = createAnchoredReceiver(graph, node, commonType, receiver, exact);
-                invokeForInlining.callTarget().replaceFirstInput(receiver, anchoredReceiver);
-
-                ResolvedJavaMethod concrete = concretes.get(i);
-                StructuredGraph calleeGraph = getGraph(concrete, callback);
-                callback.recordMethodContentsAssumption(concrete);
-                assert !IntrinsificationPhase.canIntrinsify(invokeForInlining, concrete, runtime);
-                InliningUtil.inline(invokeForInlining, calleeGraph, false);
-                replacements.add(anchoredReceiver);
-            }
-            if (shouldFallbackToInvoke()) {
-                replacements.add(null);
-            }
-            if (GraalOptions.OptTailDuplication) {
-                /*
-                 * We might want to perform tail duplication at the merge after a type switch, if there are invokes that would
-                 * benefit from the improvement in type information.
-                 */
-                FixedNode current = returnMerge;
-                int opportunities = 0;
-                do {
-                    if (current instanceof InvokeNode && ((InvokeNode) current).methodCallTarget().receiver() == originalReceiver) {
-                        opportunities++;
-                    } else if (current.inputs().contains(originalReceiver)) {
-                        opportunities++;
-                    }
-                    current = ((FixedWithNextNode) current).next();
-                } while (current instanceof FixedWithNextNode);
-                if (opportunities > 0) {
-                    metricInliningTailDuplication.increment();
-                    Debug.log("MultiTypeGuardInlineInfo starting tail duplication (%d opportunities)", opportunities);
-                    TailDuplicationPhase.tailDuplicate(returnMerge, TailDuplicationPhase.TRUE_DECISION, replacements);
-                }
-            }
-        }
-
-        private int getTypeCount(int concreteMethodIndex) {
-            int count = 0;
-            for (int i = 0; i < typesToConcretes.length; i++) {
-                if (typesToConcretes[i] == concreteMethodIndex) {
-                    count++;
-                }
-            }
-            return count;
-        }
-
-        private ResolvedJavaType getLeastCommonType(int concreteMethodIndex) {
-            ResolvedJavaType commonType = null;
-            for (int i = 0; i < typesToConcretes.length; i++) {
-                if (typesToConcretes[i] == concreteMethodIndex) {
-                    if (commonType == null) {
-                        commonType = ptypes[i].type;
-                    } else {
-                        commonType = commonType.leastCommonAncestor(ptypes[i].type);
-                    }
-                }
-            }
-            assert commonType != null;
-            return commonType;
-        }
-
-        private void inlineSingleMethod(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback) {
-            assert concretes.size() == 1 && ptypes.length > 1 && !shouldFallbackToInvoke() && notRecordedTypeProbability == 0;
-
-            MergeNode calleeEntryNode = graph.add(new MergeNode());
-            calleeEntryNode.setProbability(invoke.probability());
-            LoadHubNode receiverHub = graph.add(new LoadHubNode(invoke.methodCallTarget().receiver()));
-            graph.addBeforeFixed(invoke.node(), receiverHub);
-
-            FixedNode unknownTypeNode = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TypeCheckedInliningViolated, invoke.leafGraphId()));
-            FixedNode dispatchOnType = createDispatchOnType(graph, receiverHub, new BeginNode[] {calleeEntryNode}, unknownTypeNode);
-
-            FixedWithNextNode pred = (FixedWithNextNode) invoke.node().predecessor();
-            pred.setNext(dispatchOnType);
-            calleeEntryNode.setNext(invoke.node());
-
-            ResolvedJavaMethod concrete = concretes.get(0);
-            StructuredGraph calleeGraph = getGraph(concrete, callback);
-            assert !IntrinsificationPhase.canIntrinsify(invoke, concrete, runtime);
-            callback.recordMethodContentsAssumption(concrete);
-            InliningUtil.inline(invoke, calleeGraph, false);
-        }
-
-        private FixedNode createDispatchOnType(StructuredGraph graph, LoadHubNode objectClassNode, BeginNode[] calleeEntryNodes, FixedNode unknownTypeSux) {
-            assert ptypes.length > 1;
-
-            ResolvedJavaType[] types = new ResolvedJavaType[ptypes.length];
-            double[] probabilities = new double[ptypes.length + 1];
-            BeginNode[] successors = new BeginNode[ptypes.length + 1];
-            int[] keySuccessors = new int[ptypes.length + 1];
-            for (int i = 0; i < ptypes.length; i++) {
-                types[i] = ptypes[i].type;
-                probabilities[i] = ptypes[i].probability;
-                FixedNode entry = calleeEntryNodes[typesToConcretes[i]];
-                if (entry instanceof MergeNode) {
-                    EndNode endNode = graph.add(new EndNode());
-                    ((MergeNode) entry).addForwardEnd(endNode);
-                    entry = endNode;
-                }
-                successors[i] = BeginNode.begin(entry);
-                keySuccessors[i] = i;
-            }
-            assert !(unknownTypeSux instanceof MergeNode);
-            successors[successors.length - 1] = BeginNode.begin(unknownTypeSux);
-            probabilities[successors.length - 1] = notRecordedTypeProbability;
-            keySuccessors[successors.length - 1] = successors.length - 1;
-
-            TypeSwitchNode typeSwitch = graph.add(new TypeSwitchNode(objectClassNode, successors, probabilities, types, probabilities, keySuccessors));
-
-            return typeSwitch;
-        }
-
-        private static BeginNode createInvocationBlock(StructuredGraph graph, Invoke invoke, MergeNode returnMerge, PhiNode returnValuePhi,
-                        MergeNode exceptionMerge, PhiNode exceptionObjectPhi, int predecessors, double probability, boolean useForInlining) {
-            Invoke duplicatedInvoke = duplicateInvokeForInlining(graph, invoke, exceptionMerge, exceptionObjectPhi, useForInlining, probability);
-            BeginNode calleeEntryNode = graph.add(predecessors > 1 ? new MergeNode() : new BeginNode());
-            calleeEntryNode.setNext(duplicatedInvoke.node());
-            calleeEntryNode.setProbability(probability);
-
-            EndNode endNode = graph.add(new EndNode());
-            endNode.setProbability(probability);
-
-            duplicatedInvoke.setNext(endNode);
-            returnMerge.addForwardEnd(endNode);
-
-            if (returnValuePhi != null) {
-                returnValuePhi.addInput(duplicatedInvoke.node());
-            }
-            return calleeEntryNode;
-        }
-
-        private static Invoke duplicateInvokeForInlining(StructuredGraph graph, Invoke invoke, MergeNode exceptionMerge, PhiNode exceptionObjectPhi, boolean useForInlining, double probability) {
-            Invoke result = (Invoke) invoke.node().copyWithInputs();
-            Node callTarget = result.callTarget().copyWithInputs();
-            result.node().replaceFirstInput(result.callTarget(), callTarget);
-            result.setUseForInlining(useForInlining);
-            result.setProbability(probability);
-
-            Kind kind = invoke.node().kind();
-            if (!kind.isVoid()) {
-                FrameState stateAfter = invoke.stateAfter();
-                stateAfter = stateAfter.duplicate(stateAfter.bci);
-                stateAfter.replaceFirstInput(invoke.node(), result.node());
-                result.setStateAfter(stateAfter);
-            }
-
-            if (invoke instanceof InvokeWithExceptionNode) {
-                assert exceptionMerge != null && exceptionObjectPhi != null;
-
-                InvokeWithExceptionNode invokeWithException = (InvokeWithExceptionNode) invoke;
-                BeginNode exceptionEdge = invokeWithException.exceptionEdge();
-                ExceptionObjectNode exceptionObject = (ExceptionObjectNode) exceptionEdge.next();
-                FrameState stateAfterException = exceptionObject.stateAfter();
-
-                BeginNode newExceptionEdge = (BeginNode) exceptionEdge.copyWithInputs();
-                ExceptionObjectNode newExceptionObject = (ExceptionObjectNode) exceptionObject.copyWithInputs();
-                // set new state (pop old exception object, push new one)
-                newExceptionObject.setStateAfter(stateAfterException.duplicateModified(stateAfterException.bci, stateAfterException.rethrowException(), Kind.Object, newExceptionObject));
-                newExceptionEdge.setNext(newExceptionObject);
-
-                EndNode endNode = graph.add(new EndNode());
-                newExceptionObject.setNext(endNode);
-                exceptionMerge.addForwardEnd(endNode);
-                exceptionObjectPhi.addInput(newExceptionObject);
-
-                ((InvokeWithExceptionNode) result).setExceptionEdge(newExceptionEdge);
-            }
-            return result;
-        }
-
-        @Override
-        public String toString() {
-            StringBuilder builder = new StringBuilder(shouldFallbackToInvoke() ? "megamorphic" : "polymorphic");
-            builder.append(String.format(", %d methods with %d type checks:", concretes.size(), ptypes.length));
-            for (int i = 0; i < concretes.size(); i++) {
-                builder.append(MetaUtil.format("  %H.%n(%p):%r", concretes.get(i)));
-            }
-            return builder.toString();
-        }
-
-        @Override
-        public boolean canDeopt() {
-            return true;
-        }
-    }
-
-
-    /**
-     * Represents an inlining opportunity where the current class hierarchy leads to a monomorphic target method,
-     * but for which an assumption has to be registered because of non-final classes.
-     */
-    private static class AssumptionInlineInfo extends ExactInlineInfo {
-        public final ResolvedJavaType context;
-
-        public AssumptionInlineInfo(Invoke invoke, double weight, int level, ResolvedJavaType context, ResolvedJavaMethod concrete) {
-            super(invoke, weight, level, concrete);
-            this.context = context;
-        }
-
-        @Override
-        public void inline(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback) {
-            if (Debug.isLogEnabled()) {
-                String targetName = MetaUtil.format("%H.%n(%p):%r", invoke.methodCallTarget().targetMethod());
-                String concreteName = MetaUtil.format("%H.%n(%p):%r", concrete);
-                Debug.log("recording concrete method assumption: %s on receiver type %s -> %s", targetName, context, concreteName);
-            }
-            callback.recordConcreteMethodAssumption(invoke.methodCallTarget().targetMethod(), context, concrete);
-
-            super.inline(graph, runtime, callback);
-        }
-
-        @Override
-        public String toString() {
-            return "assumption " + MetaUtil.format("%H.%n(%p):%r", concrete);
-        }
-
-        @Override
-        public boolean canDeopt() {
-            return true;
-        }
-    }
-
-    /**
-     * Determines if inlining is possible at the given invoke node.
-     * @param invoke the invoke that should be inlined
-     * @param level the number of nested inlinings that lead to this invoke, or 0 if the invoke was part of the initial graph
-     * @param runtime a GraalRuntime instance used to determine of the invoke can be inlined and/or should be intrinsified
-     * @param callback a callback that is used to determine the weight of a specific inlining
-     * @return an instance of InlineInfo, or null if no inlining is possible at the given invoke
-     */
-    public static InlineInfo getInlineInfo(Invoke invoke, int level, GraalCodeCacheProvider runtime, Assumptions assumptions, InliningCallback callback, OptimisticOptimizations optimisticOpts) {
-        if (!(invoke.callTarget() instanceof MethodCallTargetNode)) {
-            // The invoke has already been lowered , or has been created as a low-level node. We have no method information.
-            return null;
-        }
-        ResolvedJavaMethod parent = invoke.stateAfter().method();
-        MethodCallTargetNode callTarget = invoke.methodCallTarget();
-        ResolvedJavaMethod targetMethod = callTarget.targetMethod();
-        if (targetMethod == null) {
-            return null;
-        }
-        if (!checkInvokeConditions(invoke)) {
-            return null;
-        }
-
-        if (callTarget.invokeKind() == InvokeKind.Special || targetMethod.canBeStaticallyBound()) {
-            if (checkTargetConditions(invoke, targetMethod, optimisticOpts)) {
-                double weight = callback == null ? 0 : callback.inliningWeight(parent, targetMethod, invoke);
-                return new ExactInlineInfo(invoke, weight, level, targetMethod);
-            }
-            return null;
-        }
-        ObjectStamp receiverStamp = callTarget.receiver().objectStamp();
-        ResolvedJavaType receiverType = receiverStamp.type();
-        if (receiverStamp.isExactType()) {
-            assert receiverType.isSubtypeOf(targetMethod.holder()) : receiverType + " subtype of " + targetMethod.holder() + " for " + targetMethod;
-            ResolvedJavaMethod resolved = receiverType.resolveMethodImpl(targetMethod);
-            if (checkTargetConditions(invoke, resolved, optimisticOpts)) {
-                double weight = callback == null ? 0 : callback.inliningWeight(parent, resolved, invoke);
-                return new ExactInlineInfo(invoke, weight, level, resolved);
-            }
-            return null;
-        }
-        ResolvedJavaType holder = targetMethod.holder();
-
-        if (receiverStamp.type() != null) {
-            // the invoke target might be more specific than the holder (happens after inlining: locals lose their declared type...)
-            // TODO (lstadler) fix this
-            if (receiverType != null && receiverType.isSubtypeOf(holder)) {
-                holder = receiverType;
-            }
-        }
-        // TODO (thomaswue) fix this
-        if (assumptions != null) {
-            ResolvedJavaMethod concrete = holder.uniqueConcreteMethod(targetMethod);
-            if (concrete != null) {
-                if (checkTargetConditions(invoke, concrete, optimisticOpts)) {
-                    double weight = callback == null ? 0 : callback.inliningWeight(parent, concrete, invoke);
-                    return new AssumptionInlineInfo(invoke, weight, level, holder, concrete);
-                }
-                return null;
-            }
-        }
-
-        // type check based inlining
-        return getTypeCheckedInlineInfo(invoke, level, callback, parent, targetMethod, optimisticOpts);
-    }
-
-    private static InlineInfo getTypeCheckedInlineInfo(Invoke invoke, int level, InliningCallback callback, ResolvedJavaMethod parent, ResolvedJavaMethod targetMethod, OptimisticOptimizations optimisticOpts) {
-        ProfilingInfo profilingInfo = parent.profilingInfo();
-        JavaTypeProfile typeProfile = profilingInfo.getTypeProfile(invoke.bci());
-        if (typeProfile != null) {
-            ProfiledType[] ptypes = typeProfile.getTypes();
-
-            if (ptypes != null && ptypes.length > 0) {
-                double notRecordedTypeProbability = typeProfile.getNotRecordedProbability();
-                if (ptypes.length == 1 && notRecordedTypeProbability == 0) {
-                    if (optimisticOpts.inlineMonomorphicCalls()) {
-                        ResolvedJavaType type = ptypes[0].type;
-                        ResolvedJavaMethod concrete = type.resolveMethodImpl(targetMethod);
-                        if (checkTargetConditions(invoke, concrete, optimisticOpts)) {
-                            double weight = callback == null ? 0 : callback.inliningWeight(parent, concrete, invoke);
-                            return new TypeGuardInlineInfo(invoke, weight, level, concrete, type);
-                        }
-
-                        Debug.log("not inlining %s because method can't be inlined", methodName(targetMethod, invoke));
-                        return null;
-                    } else {
-                        Debug.log("not inlining %s because GraalOptions.InlineMonomorphicCalls == false", methodName(targetMethod, invoke));
-                        return null;
-                    }
-                } else {
-                    invoke.setMegamorphic(true);
-                    if (optimisticOpts.inlinePolymorphicCalls() && notRecordedTypeProbability == 0 || optimisticOpts.inlineMegamorphicCalls() && notRecordedTypeProbability > 0) {
-                        // TODO (chaeubl) inlining of multiple methods should work differently
-                        // 1. check which methods can be inlined
-                        // 2. for those methods, use weight and probability to compute which of them should be inlined
-                        // 3. do the inlining
-                        //    a) all seen methods can be inlined -> do so and guard with deopt
-                        //    b) some methods can be inlined -> inline them and fall back to invocation if violated
-                        // TODO (chaeubl) sort types by probability
-
-                        // determine concrete methods and map type to specific method
-                        ArrayList<ResolvedJavaMethod> concreteMethods = new ArrayList<>();
-                        int[] typesToConcretes = new int[ptypes.length];
-                        for (int i = 0; i < ptypes.length; i++) {
-                            ResolvedJavaMethod concrete = ptypes[i].type.resolveMethodImpl(targetMethod);
-
-                            int index = concreteMethods.indexOf(concrete);
-                            if (index < 0) {
-                                index = concreteMethods.size();
-                                concreteMethods.add(concrete);
-                            }
-                            typesToConcretes[i] = index;
-                        }
-
-                        double totalWeight = 0;
-                        boolean canInline = true;
-                        for (ResolvedJavaMethod concrete: concreteMethods) {
-                            if (!checkTargetConditions(invoke, concrete, optimisticOpts)) {
-                                canInline = false;
-                                break;
-                            }
-                            totalWeight += callback == null ? 0 : callback.inliningWeight(parent, concrete, invoke);
-                        }
-
-                        if (canInline) {
-                            return new MultiTypeGuardInlineInfo(invoke, totalWeight, level, concreteMethods, ptypes, typesToConcretes, notRecordedTypeProbability);
-                        } else {
-                            Debug.log("not inlining %s because it is a polymorphic method call and at least one invoked method cannot be inlined", methodName(targetMethod, invoke));
-                            return null;
-                        }
-                    } else {
-                        if (!optimisticOpts.inlinePolymorphicCalls() && notRecordedTypeProbability == 0) {
-                            Debug.log("not inlining %s because GraalOptions.InlinePolymorphicCalls == false", methodName(targetMethod, invoke));
-                        } else {
-                            Debug.log("not inlining %s because GraalOptions.InlineMegamorphicCalls == false", methodName(targetMethod, invoke));
-                        }
-                        return null;
-                    }
-                }
-            }
-
-            Debug.log("not inlining %s because no types/probabilities were recorded", methodName(targetMethod, invoke));
-            return null;
-        } else {
-            Debug.log("not inlining %s because no type profile exists", methodName(targetMethod, invoke));
-            return null;
-        }
-    }
-
-    private static PiNode createAnchoredReceiver(StructuredGraph graph, FixedNode anchor, ResolvedJavaType commonType, ValueNode receiver, boolean exact) {
-        // to avoid that floating reads on receiver fields float above the type check
-        return graph.unique(new PiNode(receiver, anchor, exact ? StampFactory.exactNonNull(commonType) : StampFactory.declaredNonNull(commonType)));
-    }
-
-    private static boolean checkInvokeConditions(Invoke invoke) {
-        if (invoke.stateAfter() == null) {
-            Debug.log("not inlining %s because the invoke has no after state", methodName(invoke.methodCallTarget().targetMethod(), invoke));
-            return false;
-        }
-        if (invoke.predecessor() == null) {
-            Debug.log("not inlining %s because the invoke is dead code", methodName(invoke.methodCallTarget().targetMethod(), invoke));
-            return false;
-        }
-        if (!invoke.useForInlining()) {
-            Debug.log("not inlining %s because invoke is marked to be not used for inlining", methodName(invoke.methodCallTarget().targetMethod(), invoke));
-            return false;
-        }
-        return true;
-    }
-
-    private static boolean checkTargetConditions(Invoke invoke, JavaMethod method, OptimisticOptimizations optimisticOpts) {
-        if (method == null) {
-            Debug.log("not inlining because method is not resolved");
-            return false;
-        }
-        if (!(method instanceof ResolvedJavaMethod)) {
-            Debug.log("not inlining %s because it is unresolved", method.toString());
-            return false;
-        }
-        ResolvedJavaMethod resolvedMethod = (ResolvedJavaMethod) method;
-        if (Modifier.isNative(resolvedMethod.accessFlags())) {
-            Debug.log("not inlining %s because it is a native method", methodName(resolvedMethod, invoke));
-            return false;
-        }
-        if (Modifier.isAbstract(resolvedMethod.accessFlags())) {
-            Debug.log("not inlining %s because it is an abstract method", methodName(resolvedMethod, invoke));
-            return false;
-        }
-        if (!resolvedMethod.holder().isInitialized()) {
-            Debug.log("not inlining %s because of non-initialized class", methodName(resolvedMethod, invoke));
-            return false;
-        }
-        if (!resolvedMethod.canBeInlined()) {
-            Debug.log("not inlining %s because it is marked non-inlinable", methodName(resolvedMethod, invoke));
-            return false;
-        }
-        if (computeRecursiveInliningLevel(invoke.stateAfter(), (ResolvedJavaMethod) method) > GraalOptions.MaximumRecursiveInlining) {
-            Debug.log("not inlining %s because it exceeds the maximum recursive inlining depth", methodName(resolvedMethod, invoke));
-            return false;
-        }
-        OptimisticOptimizations calleeOpts = new OptimisticOptimizations(resolvedMethod);
-        if (calleeOpts.lessOptimisticThan(optimisticOpts)) {
-            Debug.log("not inlining %s because callee uses less optimistic optimizations than caller", methodName(resolvedMethod, invoke));
-            return false;
-        }
-
-        return true;
-    }
-
-    private static int computeRecursiveInliningLevel(FrameState state, ResolvedJavaMethod method) {
-        assert state != null;
-
-        int count = 0;
-        FrameState curState = state;
-        while (curState != null) {
-            if (curState.method() == method) {
-                count++;
-            }
-            curState = curState.outerFrameState();
-        }
-        return count;
-    }
-
-    /**
-     * Performs an actual inlining, thereby replacing the given invoke with the given inlineGraph.
-     *
-     * @param invoke the invoke that will be replaced
-     * @param inlineGraph the graph that the invoke will be replaced with
-     * @param receiverNullCheck true if a null check needs to be generated for non-static inlinings, false if no such check is required
-     */
-    public static void inline(Invoke invoke, StructuredGraph inlineGraph, boolean receiverNullCheck) {
-        InliningIdentifier identifier = new InliningIdentifier(inlineGraph.method(), invoke);
-        NodeInputList<ValueNode> parameters = invoke.callTarget().arguments();
-        StructuredGraph graph = (StructuredGraph) invoke.node().graph();
-
-        FrameState stateAfter = invoke.stateAfter();
-        assert stateAfter.isAlive();
-
-        IdentityHashMap<Node, Node> replacements = new IdentityHashMap<>();
-        ArrayList<Node> nodes = new ArrayList<>();
-        ReturnNode returnNode = null;
-        UnwindNode unwindNode = null;
-        StartNode entryPointNode = inlineGraph.start();
-        FixedNode firstCFGNode = entryPointNode.next();
-        for (Node node : inlineGraph.getNodes()) {
-            if (node == entryPointNode || node == entryPointNode.stateAfter()) {
-                // Do nothing.
-            } else if (node instanceof LocalNode) {
-                replacements.put(node, parameters.get(((LocalNode) node).index()));
-            } else {
-                nodes.add(node);
-                if (node instanceof ReturnNode) {
-                    assert returnNode == null;
-                    returnNode = (ReturnNode) node;
-                } else if (node instanceof UnwindNode) {
-                    assert unwindNode == null;
-                    unwindNode = (UnwindNode) node;
-                }
-            }
-        }
-        replacements.put(entryPointNode, BeginNode.prevBegin(invoke.node())); // ensure proper anchoring of things that where anchored to the StartNode
-
-        assert invoke.node().successors().first() != null : invoke;
-        assert invoke.node().predecessor() != null;
-
-        Map<Node, Node> duplicates = graph.addDuplicates(nodes, replacements);
-        FixedNode firstCFGNodeDuplicate = (FixedNode) duplicates.get(firstCFGNode);
-        if (receiverNullCheck) {
-            receiverNullCheck(invoke);
-        }
-        invoke.node().replaceAtPredecessor(firstCFGNodeDuplicate);
-
-        FrameState stateAtExceptionEdge = null;
-        if (invoke instanceof InvokeWithExceptionNode) {
-            InvokeWithExceptionNode invokeWithException = ((InvokeWithExceptionNode) invoke);
-            if (unwindNode != null) {
-                assert unwindNode.predecessor() != null;
-                assert invokeWithException.exceptionEdge().successors().count() == 1;
-                ExceptionObjectNode obj = (ExceptionObjectNode) invokeWithException.exceptionEdge().next();
-                stateAtExceptionEdge = obj.stateAfter();
-                UnwindNode unwindDuplicate = (UnwindNode) duplicates.get(unwindNode);
-                obj.replaceAtUsages(unwindDuplicate.exception());
-                unwindDuplicate.clearInputs();
-                Node n = obj.next();
-                obj.setNext(null);
-                unwindDuplicate.replaceAndDelete(n);
-            } else {
-                invokeWithException.killExceptionEdge();
-            }
-        } else {
-            if (unwindNode != null) {
-                UnwindNode unwindDuplicate = (UnwindNode) duplicates.get(unwindNode);
-                DeoptimizeNode deoptimizeNode = new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler, invoke.leafGraphId());
-                unwindDuplicate.replaceAndDelete(graph.add(deoptimizeNode));
-                // move the deopt upwards if there is a monitor exit that tries to use the "after exception" frame state
-                // (because there is no "after exception" frame state!)
-                if (deoptimizeNode.predecessor() instanceof MonitorExitNode) {
-                    MonitorExitNode monitorExit = (MonitorExitNode) deoptimizeNode.predecessor();
-                    if (monitorExit.stateAfter() != null && monitorExit.stateAfter().bci == FrameState.AFTER_EXCEPTION_BCI) {
-                        FrameState monitorFrameState = monitorExit.stateAfter();
-                        graph.removeFixed(monitorExit);
-                        monitorFrameState.safeDelete();
-                    }
-                }
-            }
-        }
-
-        FrameState outerFrameState = null;
-        double invokeProbability = invoke.node().probability();
-        for (Node node : duplicates.values()) {
-            if (GraalOptions.ProbabilityAnalysis) {
-                if (node instanceof FixedNode) {
-                    FixedNode fixed = (FixedNode) node;
-                    double newProbability = fixed.probability() * invokeProbability;
-                    if (GraalOptions.LimitInlinedProbability) {
-                        newProbability = Math.min(newProbability, invokeProbability);
-                    }
-                    fixed.setProbability(newProbability);
-                }
-            }
-            if (node instanceof FrameState) {
-                FrameState frameState = (FrameState) node;
-                assert frameState.bci != FrameState.BEFORE_BCI;
-                if (frameState.bci == FrameState.AFTER_BCI) {
-                    frameState.replaceAndDelete(stateAfter);
-                } else if (frameState.bci == FrameState.AFTER_EXCEPTION_BCI) {
-                    if (frameState.isAlive()) {
-                        assert stateAtExceptionEdge != null;
-                        frameState.replaceAndDelete(stateAtExceptionEdge);
-                    } else {
-                        assert stateAtExceptionEdge == null;
-                    }
-                } else {
-                    // only handle the outermost frame states
-                    if (frameState.outerFrameState() == null) {
-                        assert frameState.method() == inlineGraph.method();
-                        if (outerFrameState == null) {
-                            outerFrameState = stateAfter.duplicateModified(invoke.bci(), stateAfter.rethrowException(), invoke.node().kind());
-                            outerFrameState.setDuringCall(true);
-                        }
-                        frameState.setOuterFrameState(outerFrameState);
-                        frameState.setInliningIdentifier(identifier);
-                    }
-                }
-            }
-        }
-
-        Node returnValue = null;
-        if (returnNode != null) {
-            if (returnNode.result() instanceof LocalNode) {
-                returnValue = replacements.get(returnNode.result());
-            } else {
-                returnValue = duplicates.get(returnNode.result());
-            }
-            invoke.node().replaceAtUsages(returnValue);
-            Node returnDuplicate = duplicates.get(returnNode);
-            returnDuplicate.clearInputs();
-            Node n = invoke.next();
-            invoke.setNext(null);
-            returnDuplicate.replaceAndDelete(n);
-        }
-
-        invoke.node().clearInputs();
-        invoke.node().replaceAtUsages(null);
-        GraphUtil.killCFG(invoke.node());
-
-        if (stateAfter.usages().isEmpty()) {
-            stateAfter.safeDelete();
-        }
-    }
-
-    public static void receiverNullCheck(Invoke invoke) {
-        MethodCallTargetNode callTarget = invoke.methodCallTarget();
-        StructuredGraph graph = (StructuredGraph) invoke.graph();
-        NodeInputList<ValueNode> parameters = callTarget.arguments();
-        ValueNode firstParam = parameters.size() <= 0 ? null : parameters.get(0);
-        if (!callTarget.isStatic() && firstParam.kind() == Kind.Object && !firstParam.objectStamp().nonNull()) {
-            graph.addBeforeFixed(invoke.node(), graph.add(new FixedGuardNode(graph.unique(new IsNullNode(firstParam)), DeoptimizationReason.ClassCastException, DeoptimizationAction.InvalidateReprofile, true, invoke.leafGraphId())));
-        }
-    }
-}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/util/IntList.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,161 +0,0 @@
-/*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.util;
-
-import java.util.*;
-
-/**
- * An expandable and indexable list of {@code int}s.
- *
- * This class avoids the boxing/unboxing incurred by {@code ArrayList<Integer>}.
- */
-public final class IntList {
-
-    private int[] array;
-    private int size;
-
-    /**
-     * Creates an int list with a specified initial capacity.
-     *
-     * @param initialCapacity
-     */
-    public IntList(int initialCapacity) {
-        array = new int[initialCapacity];
-    }
-
-    /**
-     * Creates an int list with a specified initial array.
-     *
-     * @param array the initial array used for the list (no copy is made)
-     * @param initialSize the initial {@linkplain #size() size} of the list (must be less than or equal to {@code array.length}
-     */
-    public IntList(int[] array, int initialSize) {
-        assert initialSize <= array.length;
-        this.array = array;
-        this.size = initialSize;
-    }
-
-    /**
-     * Makes a new int list by copying a range from a given int list.
-     *
-     * @param other the list from which a range of values is to be copied into the new list
-     * @param startIndex the index in {@code other} at which to start copying
-     * @param length the number of values to copy from {@code other}
-     * @return a new int list whose {@linkplain #size() size} and capacity is {@code length}
-     */
-    public static IntList copy(IntList other, int startIndex, int length) {
-        return copy(other, startIndex, length, length);
-    }
-
-    /**
-     * Makes a new int list by copying a range from a given int list.
-     *
-     * @param other the list from which a range of values is to be copied into the new list
-     * @param startIndex the index in {@code other} at which to start copying
-     * @param length the number of values to copy from {@code other}
-     * @param initialCapacity the initial capacity of the new int list (must be greater or equal to {@code length})
-     * @return a new int list whose {@linkplain #size() size} is {@code length}
-     */
-    public static IntList copy(IntList other, int startIndex, int length, int initialCapacity) {
-        assert initialCapacity >= length : "initialCapacity < length";
-        int[] array = new int[initialCapacity];
-        System.arraycopy(other.array, startIndex, array, 0, length);
-        return new IntList(array, length);
-    }
-
-    public int size() {
-        return size;
-    }
-
-    /**
-     * Appends a value to the end of this list, increasing its {@linkplain #size() size} by 1.
-     *
-     * @param value the value to append
-     */
-    public void add(int value) {
-        if (size == array.length) {
-            int newSize = (size * 3) / 2 + 1;
-            array = Arrays.copyOf(array, newSize);
-        }
-        array[size++] = value;
-    }
-
-    /**
-     * Gets the value in this list at a given index.
-     *
-     * @param index the index of the element to return
-     * @throws IndexOutOfBoundsException if {@code index < 0 || index >= size()}
-     */
-    public int get(int index) {
-        if (index >= size) {
-            throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
-        }
-        return array[index];
-    }
-
-    /**
-     * Sets the size of this list to 0.
-     */
-    public void clear() {
-        size = 0;
-    }
-
-    /**
-     * Sets a value at a given index in this list.
-     *
-     * @param index the index of the element to update
-     * @param value the new value of the element
-     * @throws IndexOutOfBoundsException if {@code index < 0 || index >= size()}
-     */
-    public void set(int index, int value) {
-        if (index >= size) {
-            throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
-        }
-        array[index] = value;
-    }
-
-    /**
-     * Adjusts the {@linkplain #size() size} of this int list.
-     *
-     * If {@code newSize < size()}, the size is changed to {@code newSize}.
-     * If {@code newSize > size()}, sufficient 0 elements are {@linkplain #add(int) added}
-     * until {@code size() == newSize}.
-     *
-     * @param newSize the new size of this int list
-     */
-    public void setSize(int newSize) {
-        if (newSize < size) {
-            size = newSize;
-        } else if (newSize > size) {
-            array = Arrays.copyOf(array, newSize);
-        }
-    }
-
-    @Override
-    public String toString() {
-        if (array.length == size) {
-            return Arrays.toString(array);
-        }
-        return Arrays.toString(Arrays.copyOf(array, size));
-    }
-}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/compiler/util/Util.java	Sun Oct 07 14:11:55 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,342 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.util;
-
-import java.util.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-
-/**
- * The {@code Util} class contains a motley collection of utility methods used throughout the compiler.
- */
-public class Util {
-
-    public static final int PRINTING_LINE_WIDTH = 40;
-    public static final char SECTION_CHARACTER = '*';
-    public static final char SUB_SECTION_CHARACTER = '=';
-    public static final char SEPERATOR_CHARACTER = '-';
-
-    public static <T> boolean replaceInList(T a, T b, List<T> list) {
-        final int max = list.size();
-        for (int i = 0; i < max; i++) {
-            if (list.get(i) == a) {
-                list.set(i, b);
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Statically cast an object to an arbitrary Object type. Dynamically checked.
-     */
-    @SuppressWarnings("unchecked")
-    public static <T> T uncheckedCast(@SuppressWarnings("unused") Class<T> type, Object object) {
-        return (T) object;
-    }
-
-    /**
-     * Statically cast an object to an arbitrary Object type. Dynamically checked.
-     */
-    @SuppressWarnings("unchecked")
-    public static <T> T uncheckedCast(Object object) {
-        return (T) object;
-    }
-
-    /**
-     * Utility method to combine a base hash with the identity hash of one or more objects.
-     *
-     * @param hash the base hash
-     * @param x the object to add to the hash
-     * @return the combined hash
-     */
-    public static int hash1(int hash, Object x) {
-        // always set at least one bit in case the hash wraps to zero
-        return 0x10000000 | (hash + 7 * System.identityHashCode(x));
-    }
-
-    /**
-     * Utility method to combine a base hash with the identity hash of one or more objects.
-     *
-     * @param hash the base hash
-     * @param x the first object to add to the hash
-     * @param y the second object to add to the hash
-     * @return the combined hash
-     */
-    public static int hash2(int hash, Object x, Object y) {
-        // always set at least one bit in case the hash wraps to zero
-        return 0x20000000 | (hash + 7 * System.identityHashCode(x) + 11 * System.identityHashCode(y));
-    }
-
-    /**
-     * Utility method to combine a base hash with the identity hash of one or more objects.
-     *
-     * @param hash the base hash
-     * @param x the first object to add to the hash
-     * @param y the second object to add to the hash
-     * @param z the third object to add to the hash
-     * @return the combined hash
-     */
-    public static int hash3(int hash, Object x, Object y, Object z) {
-        // always set at least one bit in case the hash wraps to zero
-        return 0x30000000 | (hash + 7 * System.identityHashCode(x) + 11 * System.identityHashCode(y) + 13 * System.identityHashCode(z));
-    }
-
-    /**
-     * Utility method to combine a base hash with the identity hash of one or more objects.
-     *
-     * @param hash the base hash
-     * @param x the first object to add to the hash
-     * @param y the second object to add to the hash
-     * @param z the third object to add to the hash
-     * @param w the fourth object to add to the hash
-     * @return the combined hash
-     */
-    public static int hash4(int hash, Object x, Object y, Object z, Object w) {
-        // always set at least one bit in case the hash wraps to zero
-        return 0x40000000 | (hash + 7 * System.identityHashCode(x) + 11 * System.identityHashCode(y) + 13 * System.identityHashCode(z) + 17 * System.identityHashCode(w));
-    }
-
-    static {
-        assert CodeUtil.log2(2) == 1;
-        assert CodeUtil.log2(4) == 2;
-        assert CodeUtil.log2(8) == 3;
-        assert CodeUtil.log2(16) == 4;
-        assert CodeUtil.log2(32) == 5;
-        assert CodeUtil.log2(0x40000000) == 30;
-
-        assert CodeUtil.log2(2L) == 1;
-        assert CodeUtil.log2(4L) == 2;
-        assert CodeUtil.log2(8L) == 3;
-        assert CodeUtil.log2(16L) == 4;
-        assert CodeUtil.log2(32L) == 5;
-        assert CodeUtil.log2(0x4000000000000000L) == 62;
-
-        assert !CodeUtil.isPowerOf2(3);
-        assert !CodeUtil.isPowerOf2(5);
-        assert !CodeUtil.isPowerOf2(7);
-        assert !CodeUtil.isPowerOf2(-1);
-
-        assert CodeUtil.isPowerOf2(2);
-        assert CodeUtil.isPowerOf2(4);
-        assert CodeUtil.isPowerOf2(8);
-        assert CodeUtil.isPowerOf2(16);
-        assert CodeUtil.isPowerOf2(32);
-        assert CodeUtil.isPowerOf2(64);
-    }
-
-    /**
-     * Sets the element at a given position of a list and ensures that this position exists. If the list is current
-     * shorter than the position, intermediate positions are filled with a given value.
-     *
-     * @param list the list to put the element into
-     * @param pos the position at which to insert the element
-     * @param x the element that should be inserted
-     * @param filler the filler element that is used for the intermediate positions in case the list is shorter than pos
-     */
-    public static <T> void atPutGrow(List<T> list, int pos, T x, T filler) {
-        if (list.size() < pos + 1) {
-            while (list.size() < pos + 1) {
-                list.add(filler);
-            }
-            assert list.size() == pos + 1;
-        }
-
-        assert list.size() >= pos + 1;
-        list.set(pos, x);
-    }
-
-    public static void breakpoint() {
-        // do nothing.
-    }
-
-    public static void guarantee(boolean b, String string) {
-        if (!b) {
-            throw new BailoutException(string);
-        }
-    }
-
-    public static void warning(String string) {
-        TTY.println("WARNING: " + string);
-    }
-
-    public static int safeToInt(long l) {
-        assert (int) l == l;
-        return (int) l;
-    }
-
-    public static int roundUp(int number, int mod) {
-        return ((number + mod - 1) / mod) * mod;
-    }
-
-    public static void printSection(String name, char sectionCharacter) {
-
-        String header = " " + name + " ";
-        int remainingCharacters = PRINTING_LINE_WIDTH - header.length();
-        int leftPart = remainingCharacters / 2;
-        int rightPart = remainingCharacters - leftPart;
-        for (int i = 0; i < leftPart; i++) {
-            TTY.print(sectionCharacter);
-        }
-
-        TTY.print(header);
-
-        for (int i = 0; i < rightPart; i++) {
-            TTY.print(sectionCharacter);
-        }
-
-        TTY.println();
-    }
-
-    /**
-     * Prints entries in a byte array as space separated hex values to {@link TTY}.
-     *
-     * @param address an address at which the bytes are located. This is used to print an address prefix per line of output.
-     * @param array the array containing all the bytes to print
-     * @param bytesPerLine the number of values to print per line of output
-     */
-    public static void printBytes(long address, byte[] array, int bytesPerLine) {
-        printBytes(address, array, 0, array.length, bytesPerLine);
-    }
-
-    /**
-     * Prints entries in a byte array as space separated hex values to {@link TTY}.
-     *
-     * @param address an address at which the bytes are located. This is used to print an address prefix per line of output.
-     * @param array the array containing the bytes to print
-     * @param offset the offset in {@code array} of the values to print
-     * @param length the number of values from {@code array} print
-     * @param bytesPerLine the number of values to print per line of output
-     */
-    public static void printBytes(long address, byte[] array, int offset, int length, int bytesPerLine) {
-        assert bytesPerLine > 0;
-        boolean newLine = true;
-        for (int i = 0; i < length; i++) {
-            if (newLine) {
-                TTY.print("%08x: ", address + i);
-                newLine = false;
-            }
-            TTY.print("%02x ", array[i]);
-            if (i % bytesPerLine == bytesPerLine - 1) {
-                TTY.println();
-                newLine = true;
-            }
-        }
-
-        if (length % bytesPerLine != bytesPerLine) {
-            TTY.println();
-        }
-    }
-
-    public static boolean isShiftCount(int x) {
-        return 0 <= x && x < 32;
-    }
-
-    /**
-     * Determines if a given {@code int} value is the range of unsigned byte values.
-     */
-    public static boolean isUByte(int x) {
-        return (x & 0xff) == x;
-    }
-
-    /**
-     * Determines if a given {@code int} value is the range of signed byte values.
-     */
-    public static boolean isByte(int x) {
-        return (byte) x == x;
-    }
-
-    /**
-     * Determines if a given {@code long} value is the range of unsigned byte values.
-     */
-    public static boolean isUByte(long x) {
-        return (x & 0xffL) == x;
-    }
-
-    /**
-     * Determines if a given {@code long} value is the range of signed byte values.
-     */
-    public static boolean isByte(long l) {
-        return (byte) l == l;
-    }
-
-    /**
-     * Determines if a given {@code long} value is the range of unsigned int values.
-     */
-    public static boolean isUInt(long x) {
-        return (x & 0xffffffffL) == x;
-    }
-
-    /**
-     * Determines if a given {@code long} value is the range of signed int values.
-     */
-    public static boolean isInt(long l) {
-        return (int) l == l;
-    }
-    /**
-     * Determines if a given {@code int} value is the range of signed short values.
-     */
-    public static boolean isShort(int x) {
-        return (short) x == x;
-    }
-
-    public static boolean is32bit(long x) {
-        return -0x80000000L <= x && x < 0x80000000L;
-    }
-
-    public static short safeToShort(int v) {
-        assert isShort(v);
-        return (short) v;
-    }
-
-    public static boolean isFixed(Node n) {
-        return n instanceof FixedNode;
-    }
-
-    public static boolean isFloating(Node n) {
-        return n instanceof FloatingNode;
-    }
-
-    /**
-     * Creates an array of integers of length "size", in which each number from 0 to (size - 1) occurs exactly once. The
-     * integers are sorted using the given comparator. This can be used to create a sorting for arrays that cannot be
-     * modified directly.
-     *
-     * @param size The size of the range to be sorted.
-     * @param comparator A comparator that is used to compare indexes.
-     * @return An array of integers that contains each number from 0 to (size - 1) exactly once, sorted using the
-     *         comparator.
-     */
-    public static Integer[] createSortedPermutation(int size, Comparator<Integer> comparator) {
-        Integer[] indexes = new Integer[size];
-        for (int i = 0; i < size; i++) {
-            indexes[i] = i;
-        }
-        Arrays.sort(indexes, comparator);
-        return indexes;
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2009, 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 com.oracle.graal.phases;
+
+
+
+/**
+ * This class encapsulates options that control the behavior of the Graal compiler.
+ *
+ * (thomaswue) WARNING: Fields of this class are treated as final by Graal.
+ */
+public final class GraalOptions {
+
+    // Checkstyle: stop
+    private static final boolean ____ = false;
+    // Checkstyle: resume
+
+    public static int     Threads                            = 4;
+
+    // inlining settings
+    public static boolean Inline                             = true;
+    public static boolean Intrinsify                         = true;
+           static boolean InlineMonomorphicCalls             = true;
+           static boolean InlinePolymorphicCalls             = true;
+           static boolean InlineMegamorphicCalls             = ____;
+    public static int     InliningPolicy                     = 4;
+    public static int     WeightComputationPolicy            = 2;
+    public static int     MaximumTrivialSize                 = 10;
+    public static int     MaximumInlineLevel                 = 30;
+    public static int     MaximumDesiredSize                 = 3000;
+    public static int     MaximumRecursiveInlining           = 1;
+    public static int     SmallCompiledCodeSize              = 2000;
+    public static boolean LimitInlinedProbability            = ____;
+    // WeightBasedInliningPolicy (0)
+    public static boolean ParseBeforeInlining                = ____;
+    public static float   InliningSizePenaltyExp             = 20;
+    public static float   MaximumInlineWeight                = 1.25f;
+    public static float   InliningSizePenalty                = 1;
+    // StaticSizeBasedInliningPolicy (1), MinimumCodeSizeBasedInlining (2),
+    // DynamicSizeBasedInliningPolicy (3)
+    public static int     MaximumInlineSize                  = 35;
+    // GreedySizeBasedInlining (4)
+    public static int     MaximumGreedyInlineSize            = 100;
+    public static int     InliningBonusPerTransferredValue   = 10;
+    // Common options for inlining policies 1 to 4
+    public static float   NestedInliningSizeRatio            = 1f;
+    public static float   BoostInliningForEscapeAnalysis     = 2f;
+    public static float   ProbabilityCapForInlining          = 1f;
+
+    // escape analysis settings
+    public static boolean PartialEscapeAnalysis              = true;
+
+    public static double TailDuplicationProbability          = 0.5;
+    public static int    TailDuplicationTrivialSize          = 1;
+
+    // absolute probability analysis
+    public static boolean ProbabilityAnalysis                = true;
+    public static int     LoopFrequencyPropagationPolicy     = -2;
+
+    // profiling information
+    public static int     DeoptsToDisableOptimisticOptimization = 40;
+    public static boolean PrintDisabledOptimisticOptimizations = true;
+    public static int     MatureExecutionsBranch             = 1;
+    public static int     MatureExecutionsPerSwitchCase      = 1;
+    public static int     MatureExecutionsTypeProfile        = 1;
+
+    // comilation queue
+    public static int     TimedBootstrap                     = -1;
+    public static boolean PriorityCompileQueue               = true;
+    public static int     SlowQueueCutoff                    = 100000;
+    public static boolean SlowCompileThreads                 = ____;
+    public static boolean DynamicCompilePriority             = ____;
+
+    // graph caching
+    public static boolean CacheGraphs                        = true;
+    public static int     GraphCacheSize                     = 1000;
+    public static boolean PrintGraphCache                    = ____;
+
+    //rematerialize settings
+    public static float   MinimumUsageProbability            = 0.95f;
+
+    //loop transform settings TODO (gd) tune
+    public static boolean LoopPeeling                        = true;
+    public static boolean ReassociateInvariants              = true;
+    public static boolean FullUnroll                         = true;
+    public static boolean LoopUnswitch                       = true;
+    public static int     FullUnrollMaxNodes                 = 150;
+    public static int     ExactFullUnrollMaxNodes            = 600;
+    public static float   MinimumPeelProbability             = 0.35f;
+    public static int     LoopMaxUnswitch                    = 3;
+    public static int     LoopUnswitchMaxIncrease            = 50;
+    public static int     LoopUnswitchUncertaintyBoost       = 5;
+
+    // debugging settings
+    public static int     MethodEndBreakpointGuards          = 0;
+    public static boolean ZapStackOnMethodEntry              = ____;
+    public static boolean DeoptALot                          = ____;
+    public static boolean VerifyPhases                       = true;
+    public static boolean CreateDeoptInfo                    = ____;
+
+    public static String  PrintFilter                        = null;
+
+    // printing settings
+    public static boolean PrintLIR                           = ____;
+    public static boolean PrintCFGToFile                     = ____;
+
+    // Debug settings:
+    public static boolean Debug                              = true;
+    public static boolean PerThreadDebugValues               = ____;
+    public static boolean SummarizeDebugValues               = ____;
+    public static boolean SummarizePerPhase                  = ____;
+    public static String Dump                                = null;
+    public static String Meter                               = null;
+    public static String Time                                = null;
+    public static String Log                                 = null;
+    public static String LogFile                             = null;
+    public static String MethodFilter                        = null;
+    public static boolean DumpOnError                        = ____;
+
+    // Ideal graph visualizer output settings
+    public static boolean PrintBinaryGraphs                  = ____;
+    public static boolean PrintCFG                           = true;
+    public static boolean PrintIdealGraphFile                = ____;
+    public static String  PrintIdealGraphAddress             = "127.0.0.1";
+    public static int     PrintIdealGraphPort                = 4444;
+    public static int     PrintBinaryGraphPort               = 4445;
+
+    // Other printing settings
+    public static boolean PrintQueue                         = ____;
+    public static boolean PrintCompilation                   = ____;
+    public static boolean PrintProfilingInformation          = ____;
+    public static boolean PrintXirTemplates                  = ____;
+    public static boolean PrintIRWithLIR                     = ____;
+    public static boolean PrintAssembly                      = ____;
+    public static boolean PrintCodeBytes                     = ____;
+    public static int     PrintAssemblyBytesPerLine          = 16;
+    public static boolean PrintBailout                       = ____;
+    public static int     TraceLinearScanLevel               = 0;
+    public static boolean TraceRegisterAllocation            = false;
+    public static int     TraceLIRGeneratorLevel             = 0;
+    public static boolean TraceEscapeAnalysis                = ____;
+    public static int     TraceBytecodeParserLevel           = 0;
+    public static boolean PrintBailouts                      = true;
+    public static boolean ExitVMOnBailout                    = ____;
+    public static boolean ExitVMOnException                  = true;
+
+    // state merging settings
+    public static boolean AssumeVerifiedBytecode             = true;
+
+    // Code generator settings
+    public static boolean CheckCastElimination               = true;
+    public static boolean CullFrameStates                    = ____;
+    public static boolean UseProfilingInformation            = true;
+           static boolean RemoveNeverExecutedCode            = true;
+           static boolean UseExceptionProbability            = true;
+    public static boolean AllowExplicitExceptionChecks       = true;
+    public static boolean OmitHotExceptionStacktrace         = ____;
+    public static boolean GenSafepoints                      = true;
+    public static boolean GenLoopSafepoints                  = true;
+           static boolean UseTypeCheckHints                  = true;
+    public static boolean InlineVTableStubs                  = true;
+    public static boolean AlwaysInlineVTableStubs            = ____;
+
+    public static boolean GenAssertionCode                   = ____;
+    public static boolean AlignCallsForPatching              = true;
+    public static boolean ResolveClassBeforeStaticInvoke     = true;
+
+    // Translating tableswitch instructions
+    public static int     SequentialSwitchLimit              = 4;
+    public static int     RangeTestsSwitchDensity            = 5;
+    public static double  MinTableSwitchDensity              = 0.5;
+
+    public static boolean DetailedAsserts                    = ____;
+
+    // Runtime settings
+    public static int     ReadPrefetchInstr                  = 0;
+    public static int     StackShadowPages                   = 2;
+
+    // Assembler settings
+    public static boolean CommentedAssembly                  = ____;
+    public static boolean PrintLIRWithAssembly               = ____;
+
+    public static boolean SupportJsrBytecodes                = true;
+
+    public static boolean OptAssumptions                     = true;
+    public static boolean OptReadElimination                 = true;
+    public static boolean OptGVN                             = true;
+    public static boolean OptCanonicalizer                   = true;
+    public static boolean ScheduleOutOfLoops                 = true;
+    public static boolean OptReorderLoops                    = true;
+    public static boolean OptEliminateGuards                 = true;
+    public static boolean OptImplicitNullChecks              = true;
+    public static boolean OptLivenessAnalysis                = true;
+    public static boolean OptLoopTransform                   = true;
+    public static boolean OptSafepointElimination            = true;
+    public static boolean FloatingReads                      = true;
+    public static boolean OptTailDuplication                 = true;
+
+    /**
+     * Prints all the available GraalOptions.
+     */
+    public static boolean PrintFlags                           = false;
+
+    /**
+     * Counts the various paths taken through snippets.
+     */
+    public static boolean SnippetCounters = false;
+
+    /**
+     * If the probability that a checkcast will hit one the profiled types (up to {@link #CheckcastMaxHints})
+     * is below this value, the checkcast will be compiled without hints.
+     */
+    public static double CheckcastMinHintHitProbability = 0.5;
+
+    /**
+     * The maximum number of hint types that will be used when compiling a checkcast for which
+     * profiling information is available. Note that {@link #CheckcastMinHintHitProbability}
+     * also influences whether hints are used.
+     */
+    public static int CheckcastMaxHints = 2;
+
+    /**
+     * @see #CheckcastMinHintHitProbability
+     */
+    public static double InstanceOfMinHintHitProbability = 0.5;
+
+    /**
+     * @see #CheckcastMaxHints
+     */
+    public static int InstanceOfMaxHints = 1;
+
+    static {
+        // turn detailed assertions on when the general assertions are on (misusing the assert keyword for this)
+        assert (DetailedAsserts = true) == true;
+        assert (CommentedAssembly = true) == true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/OptimisticOptimizations.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 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 com.oracle.graal.phases;
+
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.debug.*;
+
+
+
+public final class OptimisticOptimizations {
+    public static final OptimisticOptimizations ALL = new OptimisticOptimizations(EnumSet.allOf(Optimization.class));
+    public static final OptimisticOptimizations NONE = new OptimisticOptimizations(EnumSet.noneOf(Optimization.class));
+    private static final DebugMetric disabledOptimisticOptsMetric = Debug.metric("DisabledOptimisticOpts");
+
+    private static enum Optimization {
+        RemoveNeverExecutedCode,
+        UseTypeCheckedInlining,
+        UseTypeCheckHints,
+        UseExceptionProbability
+    }
+
+    private final Set<Optimization> enabledOpts;
+
+    public OptimisticOptimizations(ResolvedJavaMethod method) {
+        this.enabledOpts = EnumSet.noneOf(Optimization.class);
+
+        ProfilingInfo profilingInfo = method.profilingInfo();
+        if (checkDeoptimizations(profilingInfo, DeoptimizationReason.UnreachedCode)) {
+            enabledOpts.add(Optimization.RemoveNeverExecutedCode);
+        }
+        if (checkDeoptimizations(profilingInfo, DeoptimizationReason.TypeCheckedInliningViolated)) {
+            enabledOpts.add(Optimization.UseTypeCheckedInlining);
+        }
+        if (checkDeoptimizations(profilingInfo, DeoptimizationReason.OptimizedTypeCheckViolated)) {
+            enabledOpts.add(Optimization.UseTypeCheckHints);
+        }
+        if (checkDeoptimizations(profilingInfo, DeoptimizationReason.NotCompiledExceptionHandler)) {
+            enabledOpts.add(Optimization.UseExceptionProbability);
+        }
+    }
+
+    private OptimisticOptimizations(Set<Optimization> enabledOpts) {
+        this.enabledOpts = enabledOpts;
+    }
+
+    public void log(JavaMethod method) {
+        for (Optimization opt: Optimization.values()) {
+            if (!enabledOpts.contains(opt)) {
+                if (GraalOptions.PrintDisabledOptimisticOptimizations) {
+                    TTY.println("WARN: deactivated optimistic optimization %s for %s", opt.name(), MetaUtil.format("%H.%n(%p)", method));
+                }
+                disabledOptimisticOptsMetric.increment();
+            }
+        }
+    }
+
+    public boolean removeNeverExecutedCode() {
+        return GraalOptions.RemoveNeverExecutedCode && enabledOpts.contains(Optimization.RemoveNeverExecutedCode);
+    }
+
+    public boolean useTypeCheckHints() {
+        return GraalOptions.UseTypeCheckHints && enabledOpts.contains(Optimization.UseTypeCheckHints);
+    }
+
+    public boolean inlineMonomorphicCalls() {
+        return GraalOptions.InlineMonomorphicCalls && enabledOpts.contains(Optimization.UseTypeCheckedInlining);
+    }
+
+    public boolean inlinePolymorphicCalls() {
+        return GraalOptions.InlinePolymorphicCalls && enabledOpts.contains(Optimization.UseTypeCheckedInlining);
+    }
+
+    public boolean inlineMegamorphicCalls() {
+        return GraalOptions.InlineMegamorphicCalls && enabledOpts.contains(Optimization.UseTypeCheckedInlining);
+    }
+
+    public boolean useExceptionProbability() {
+        return GraalOptions.UseExceptionProbability && enabledOpts.contains(Optimization.UseExceptionProbability);
+    }
+
+    public boolean lessOptimisticThan(OptimisticOptimizations other) {
+        for (Optimization opt: Optimization.values()) {
+            if (!enabledOpts.contains(opt) && other.enabledOpts.contains(opt)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static boolean checkDeoptimizations(ProfilingInfo profilingInfo, DeoptimizationReason reason) {
+        return profilingInfo.getDeoptimizationCount(reason) < GraalOptions.DeoptsToDisableOptimisticOptimization;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/MergeableState.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.phases.graph;
+
+import java.util.*;
+
+import com.oracle.graal.nodes.*;
+
+public interface MergeableState <T> {
+    T clone();
+    boolean merge(MergeNode merge, List<T> withStates);
+    void loopBegin(LoopBeginNode loopBegin);
+    void loopEnds(LoopBeginNode loopBegin, List<T> loopEndStates);
+    void afterSplit(FixedNode node);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/PostOrderNodeIterator.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.phases.graph;
+
+import java.util.*;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+
+/**
+ * A PostOrderNodeIterator iterates the fixed nodes of the graph in post order starting from a specified fixed node.<br>
+ * For this iterator the CFG is defined by the classical CFG nodes ({@link ControlSplitNode}, {@link MergeNode}...) and the {@link FixedWithNextNode#next() next} pointers
+ * of {@link FixedWithNextNode}.<br>
+ * While iterating it maintains a user-defined state by calling the methods available in {@link MergeableState}.
+ *
+ * @param <T> the type of {@link MergeableState} handled by this PostOrderNodeIterator
+ */
+public abstract class PostOrderNodeIterator<T extends MergeableState<T>> {
+
+    private final NodeBitMap visitedEnds;
+    private final Deque<FixedNode> nodeQueue;
+    private final IdentityHashMap<FixedNode, T> nodeStates;
+    private final FixedNode start;
+
+    protected T state;
+
+    public PostOrderNodeIterator(FixedNode start, T initialState) {
+        visitedEnds = start.graph().createNodeBitMap();
+        nodeQueue = new ArrayDeque<>();
+        nodeStates = new IdentityHashMap<>();
+        this.start = start;
+        this.state = initialState;
+    }
+
+    public void apply() {
+        FixedNode current = start;
+
+        do {
+            if (current instanceof InvokeWithExceptionNode) {
+                invoke((Invoke) current);
+                queueSuccessors(current, null);
+                current = nextQueuedNode();
+            } else if (current instanceof LoopBeginNode) {
+                state.loopBegin((LoopBeginNode) current);
+                nodeStates.put(current, state);
+                state = state.clone();
+                loopBegin((LoopBeginNode) current);
+                current = ((LoopBeginNode) current).next();
+                assert current != null;
+            } else if (current instanceof LoopEndNode) {
+                loopEnd((LoopEndNode) current);
+                finishLoopEnds((LoopEndNode) current);
+                current = nextQueuedNode();
+            } else if (current instanceof MergeNode) {
+                merge((MergeNode) current);
+                current = ((MergeNode) current).next();
+                assert current != null;
+            } else if (current instanceof FixedWithNextNode) {
+                FixedNode next = ((FixedWithNextNode) current).next();
+                assert next != null : current;
+                node(current);
+                current = next;
+            } else if (current instanceof EndNode) {
+                end((EndNode) current);
+                queueMerge((EndNode) current);
+                current = nextQueuedNode();
+            } else if (current instanceof DeoptimizeNode) {
+                deoptimize((DeoptimizeNode) current);
+                current = nextQueuedNode();
+            } else if (current instanceof ReturnNode) {
+                returnNode((ReturnNode) current);
+                current = nextQueuedNode();
+            } else if (current instanceof UnwindNode) {
+                unwind((UnwindNode) current);
+                current = nextQueuedNode();
+            } else if (current instanceof ControlSplitNode) {
+                Set<Node> successors = controlSplit((ControlSplitNode) current);
+                queueSuccessors(current, successors);
+                current = nextQueuedNode();
+            } else {
+                assert false : current;
+            }
+        } while(current != null);
+    }
+
+    private void queueSuccessors(FixedNode x, Set<Node> successors) {
+        nodeStates.put(x, state);
+        if (successors != null) {
+            for (Node node : successors) {
+                if (node != null) {
+                    nodeStates.put((FixedNode) node.predecessor(), state);
+                    nodeQueue.addFirst((FixedNode) node);
+                }
+            }
+        } else {
+            for (Node node : x.successors()) {
+                if (node != null) {
+                    nodeQueue.addFirst((FixedNode) node);
+                }
+            }
+        }
+    }
+
+    private FixedNode nextQueuedNode() {
+        int maxIterations = nodeQueue.size();
+        while (maxIterations-- > 0) {
+            FixedNode node = nodeQueue.removeFirst();
+            if (node instanceof MergeNode) {
+                MergeNode merge = (MergeNode) node;
+                state = nodeStates.get(merge.forwardEndAt(0)).clone();
+                ArrayList<T> states = new ArrayList<>(merge.forwardEndCount() - 1);
+                for (int i = 1; i < merge.forwardEndCount(); i++) {
+                    T other = nodeStates.get(merge.forwardEndAt(i));
+                    assert other != null;
+                    states.add(other);
+                }
+                boolean ready = state.merge(merge, states);
+                if (ready) {
+                    return merge;
+                } else {
+                    nodeQueue.addLast(merge);
+                }
+            } else {
+                assert node.predecessor() != null;
+                state = nodeStates.get(node.predecessor()).clone();
+                state.afterSplit(node);
+                return node;
+            }
+        }
+        return null;
+    }
+
+    private void finishLoopEnds(LoopEndNode end) {
+        assert !visitedEnds.isMarked(end);
+        assert !nodeStates.containsKey(end);
+        nodeStates.put(end, state);
+        visitedEnds.mark(end);
+        LoopBeginNode begin = end.loopBegin();
+        boolean endsVisited = true;
+        for (LoopEndNode le : begin.loopEnds()) {
+            if (!visitedEnds.isMarked(le)) {
+                endsVisited = false;
+                break;
+            }
+        }
+        if (endsVisited) {
+            ArrayList<T> states = new ArrayList<>(begin.loopEnds().count());
+            for (LoopEndNode le : begin.orderedLoopEnds()) {
+                states.add(nodeStates.get(le));
+            }
+            T loopBeginState = nodeStates.get(begin);
+            if (loopBeginState != null) {
+                loopBeginState.loopEnds(begin, states);
+            }
+        }
+    }
+
+    private void queueMerge(EndNode end) {
+        assert !visitedEnds.isMarked(end);
+        assert !nodeStates.containsKey(end);
+        nodeStates.put(end, state);
+        visitedEnds.mark(end);
+        MergeNode merge = end.merge();
+        boolean endsVisited = true;
+        for (int i = 0; i < merge.forwardEndCount(); i++) {
+            if (!visitedEnds.isMarked(merge.forwardEndAt(i))) {
+                endsVisited = false;
+                break;
+            }
+        }
+        if (endsVisited) {
+            nodeQueue.add(merge);
+        }
+    }
+
+    protected abstract void node(FixedNode node);
+
+    protected void end(EndNode endNode) {
+        node(endNode);
+    }
+
+    protected void merge(MergeNode merge) {
+        node(merge);
+    }
+
+    protected void loopBegin(LoopBeginNode loopBegin) {
+        node(loopBegin);
+    }
+
+    protected void loopEnd(LoopEndNode loopEnd) {
+        node(loopEnd);
+    }
+
+    protected void deoptimize(DeoptimizeNode deoptimize) {
+        node(deoptimize);
+    }
+
+    protected Set<Node> controlSplit(ControlSplitNode controlSplit) {
+        node(controlSplit);
+        return null;
+    }
+
+    protected void returnNode(ReturnNode returnNode) {
+        node(returnNode);
+    }
+
+    protected void invoke(Invoke invoke) {
+        node(invoke.node());
+    }
+
+    protected void unwind(UnwindNode unwind) {
+        node(unwind);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/package-info.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ *
+ */
+package com.oracle.graal.phases.graph;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/package-info.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * The top-level package in Graal containing options, metrics and timers.
+ *
+ * Graal is intended to be used with multiple JVM's so makes no use of or reference to classes for a specific JVM.
+ */
+package com.oracle.graal.phases;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/BoxingEliminationPhase.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.phases.phases;
+
+import static com.oracle.graal.graph.iterators.NodePredicates.*;
+
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.iterators.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.virtual.*;
+
+public class BoxingEliminationPhase extends Phase {
+
+    private int virtualIds = Integer.MIN_VALUE;
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        if (graph.getNodes(UnboxNode.class).isNotEmpty()) {
+
+            Map<PhiNode, PhiNode> phiReplacements = new HashMap<>();
+            for (UnboxNode unboxNode : graph.getNodes(UnboxNode.class)) {
+                tryEliminate(graph, unboxNode, phiReplacements);
+            }
+
+            new DeadCodeEliminationPhase().apply(graph);
+
+            for (BoxNode boxNode : graph.getNodes(BoxNode.class)) {
+                tryEliminate(boxNode);
+            }
+        }
+    }
+
+    private void tryEliminate(StructuredGraph graph, UnboxNode unboxNode, Map<PhiNode, PhiNode> phiReplacements) {
+        ValueNode unboxedValue = unboxedValue(unboxNode.source(), unboxNode.destinationKind(), phiReplacements);
+        if (unboxedValue != null) {
+            assert unboxedValue.kind() == unboxNode.kind();
+            unboxNode.replaceAtUsages(unboxedValue);
+            graph.removeFixed(unboxNode);
+        }
+    }
+
+    private PhiNode getReplacementPhi(PhiNode phiNode, Kind kind, Map<PhiNode, PhiNode> phiReplacements) {
+        if (!phiReplacements.containsKey(phiNode)) {
+            PhiNode result = null;
+            ObjectStamp stamp = phiNode.objectStamp();
+            if (stamp.nonNull() && stamp.isExactType()) {
+                ResolvedJavaType type = stamp.type();
+                if (type != null && type.toJava() == kind.toBoxedJavaClass()) {
+                    StructuredGraph graph = (StructuredGraph) phiNode.graph();
+                    result = graph.add(new PhiNode(kind, phiNode.merge()));
+                    phiReplacements.put(phiNode, result);
+                    virtualizeUsages(phiNode, result, type);
+                    int i = 0;
+                    for (ValueNode n : phiNode.values()) {
+                        ValueNode unboxedValue = unboxedValue(n, kind, phiReplacements);
+                        if (unboxedValue != null) {
+                            assert unboxedValue.kind() == kind;
+                            result.addInput(unboxedValue);
+                        } else {
+                            UnboxNode unboxNode = graph.add(new UnboxNode(kind, n));
+                            FixedNode pred = phiNode.merge().phiPredecessorAt(i);
+                            graph.addBeforeFixed(pred, unboxNode);
+                            result.addInput(unboxNode);
+                        }
+                        ++i;
+                    }
+                }
+            }
+        }
+        return phiReplacements.get(phiNode);
+    }
+
+    private ValueNode unboxedValue(ValueNode n, Kind kind, Map<PhiNode, PhiNode> phiReplacements) {
+        if (n instanceof BoxNode) {
+            BoxNode boxNode = (BoxNode) n;
+            return boxNode.source();
+        } else if (n instanceof PhiNode) {
+            PhiNode phiNode = (PhiNode) n;
+            return getReplacementPhi(phiNode, kind, phiReplacements);
+        } else {
+            return null;
+        }
+    }
+
+    private void tryEliminate(BoxNode boxNode) {
+
+        assert boxNode.objectStamp().isExactType();
+        virtualizeUsages(boxNode, boxNode.source(), boxNode.objectStamp().type());
+
+        if (boxNode.usages().filter(isNotA(VirtualState.class)).isNotEmpty()) {
+            // Elimination failed, because boxing object escapes.
+            return;
+        }
+
+        FrameState stateAfter = boxNode.stateAfter();
+        boxNode.setStateAfter(null);
+        stateAfter.safeDelete();
+
+        ((StructuredGraph) boxNode.graph()).removeFixed(boxNode);
+    }
+
+    private void virtualizeUsages(ValueNode boxNode, ValueNode replacement, ResolvedJavaType exactType) {
+        ValueNode virtualValueNode = null;
+        VirtualObjectNode virtualObjectNode = null;
+        for (Node n : boxNode.usages().filter(NodePredicates.isA(VirtualState.class)).snapshot()) {
+            if (virtualValueNode == null) {
+                virtualObjectNode = n.graph().unique(new BoxedVirtualObjectNode(virtualIds++, exactType, replacement));
+            }
+            n.replaceFirstInput(boxNode, virtualObjectNode);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/CanonicalizerPhase.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,331 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.phases.phases;
+
+import java.util.*;
+import java.util.concurrent.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.Graph.InputChangedListener;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.util.*;
+
+public class CanonicalizerPhase extends Phase {
+    private static final int MAX_ITERATION_PER_NODE = 10;
+    private static final DebugMetric METRIC_CANONICALIZED_NODES = Debug.metric("CanonicalizedNodes");
+    private static final DebugMetric METRIC_CANONICALIZATION_CONSIDERED_NODES = Debug.metric("CanonicalizationConsideredNodes");
+    private static final DebugMetric METRIC_INFER_STAMP_CALLED = Debug.metric("InferStampCalled");
+    private static final DebugMetric METRIC_STAMP_CHANGED = Debug.metric("StampChanged");
+    private static final DebugMetric METRIC_SIMPLIFICATION_CONSIDERED_NODES = Debug.metric("SimplificationConsideredNodes");
+    public static final DebugMetric METRIC_GLOBAL_VALUE_NUMBERING_HITS = Debug.metric("GlobalValueNumberingHits");
+
+    private final int newNodesMark;
+    private final TargetDescription target;
+    private final Assumptions assumptions;
+    private final MetaAccessProvider runtime;
+    private final IsImmutablePredicate immutabilityPredicate;
+    private final Iterable<Node> initWorkingSet;
+
+    private NodeWorkList workList;
+    private Tool tool;
+    private List<Node> snapshotTemp;
+
+    public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions) {
+        this(target, runtime, assumptions, null, 0, null);
+    }
+
+    /**
+     * @param target
+     * @param runtime
+     * @param assumptions
+     * @param workingSet the initial working set of nodes on which the canonicalizer works, should be an auto-grow node bitmap
+     * @param immutabilityPredicate
+     */
+    public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, Iterable<Node> workingSet, IsImmutablePredicate immutabilityPredicate) {
+        this(target, runtime, assumptions, workingSet, 0, immutabilityPredicate);
+    }
+
+    /**
+     * @param newNodesMark only the {@linkplain Graph#getNewNodes(int) new nodes} specified by
+     *            this mark are processed otherwise all nodes in the graph are processed
+     */
+    public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, int newNodesMark, IsImmutablePredicate immutabilityPredicate) {
+        this(target, runtime, assumptions, null, newNodesMark, immutabilityPredicate);
+    }
+
+    private CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, Iterable<Node> workingSet, int newNodesMark, IsImmutablePredicate immutabilityPredicate) {
+        this.newNodesMark = newNodesMark;
+        this.target = target;
+        this.assumptions = assumptions;
+        this.runtime = runtime;
+        this.immutabilityPredicate = immutabilityPredicate;
+        this.initWorkingSet = workingSet;
+        this.snapshotTemp = new ArrayList<>();
+    }
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        if (initWorkingSet == null) {
+            workList = graph.createNodeWorkList(newNodesMark == 0, MAX_ITERATION_PER_NODE);
+            if (newNodesMark > 0) {
+                workList.addAll(graph.getNewNodes(newNodesMark));
+            }
+        } else {
+            workList = graph.createNodeWorkList(false, MAX_ITERATION_PER_NODE);
+            workList.addAll(initWorkingSet);
+        }
+        tool = new Tool(workList, runtime, target, assumptions, immutabilityPredicate);
+        processWorkSet(graph);
+    }
+
+    public interface IsImmutablePredicate {
+        /**
+         * Determines if a given constant is an object/array whose current
+         * fields/elements will never change.
+         */
+        boolean apply(Constant constant);
+    }
+
+    private void processWorkSet(StructuredGraph graph) {
+        graph.trackInputChange(new InputChangedListener() {
+            @Override
+            public void inputChanged(Node node) {
+                workList.addAgain(node);
+            }
+        });
+
+        for (Node n : workList) {
+            processNode(n, graph);
+        }
+
+        graph.stopTrackingInputChange();
+    }
+
+    private void processNode(Node node, StructuredGraph graph) {
+        if (node.isAlive()) {
+            METRIC_PROCESSED_NODES.increment();
+
+            if (tryGlobalValueNumbering(node, graph)) {
+                return;
+            }
+            int mark = graph.getMark();
+            if (!tryKillUnused(node)) {
+                node.inputs().filter(GraphUtil.isFloatingNode()).snapshotTo(snapshotTemp);
+                if (!tryCanonicalize(node, graph, tool)) {
+                    tryInferStamp(node, graph);
+                } else {
+                    for (Node in : snapshotTemp) {
+                        if (in.isAlive() && in.usages().isEmpty()) {
+                            GraphUtil.killWithUnusedFloatingInputs(in);
+                        }
+                    }
+                }
+                snapshotTemp.clear();
+            }
+
+            for (Node newNode : graph.getNewNodes(mark)) {
+                workList.add(newNode);
+            }
+        }
+    }
+
+    private static boolean tryKillUnused(Node node) {
+        if (node.isAlive() && GraphUtil.isFloatingNode().apply(node) && node.usages().isEmpty()) {
+            GraphUtil.killWithUnusedFloatingInputs(node);
+            return true;
+        }
+        return false;
+    }
+
+    public static boolean tryGlobalValueNumbering(Node node, StructuredGraph graph) {
+        if (node.getNodeClass().valueNumberable()) {
+            Node newNode = graph.findDuplicate(node);
+            if (newNode != null) {
+                assert !(node instanceof FixedNode || newNode instanceof FixedNode);
+                node.replaceAtUsages(newNode);
+                node.safeDelete();
+                METRIC_GLOBAL_VALUE_NUMBERING_HITS.increment();
+                Debug.log("GVN applied and new node is %1s", newNode);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public static boolean tryCanonicalize(final Node node, final StructuredGraph graph, final SimplifierTool tool) {
+        if (node instanceof Canonicalizable) {
+            assert !(node instanceof Simplifiable);
+            METRIC_CANONICALIZATION_CONSIDERED_NODES.increment();
+            return Debug.scope("CanonicalizeNode", node, new Callable<Boolean>(){
+                public Boolean call() {
+                    ValueNode canonical = ((Canonicalizable) node).canonical(tool);
+//     cases:                                           original node:
+//                                         |Floating|Fixed-unconnected|Fixed-connected|
+//                                         --------------------------------------------
+//                                     null|   1    |        X        |       3       |
+//                                         --------------------------------------------
+//                                 Floating|   2    |        X        |       4       |
+//       canonical node:                   --------------------------------------------
+//                        Fixed-unconnected|   X    |        X        |       5       |
+//                                         --------------------------------------------
+//                          Fixed-connected|   2    |        X        |       6       |
+//                                         --------------------------------------------
+//       X: must not happen (checked with assertions)
+                    if (canonical == node) {
+                        Debug.log("Canonicalizer: work on %s", node);
+                        return false;
+                    } else {
+                        Debug.log("Canonicalizer: replacing %s with %s", node, canonical);
+                        METRIC_CANONICALIZED_NODES.increment();
+                        if (node instanceof FloatingNode) {
+                            if (canonical == null) {
+                                // case 1
+                                graph.removeFloating((FloatingNode) node);
+                            } else {
+                                // case 2
+                                assert !(canonical instanceof FixedNode) || (canonical.predecessor() != null || canonical instanceof StartNode) : node + " -> " + canonical +
+                                                " : replacement should be floating or fixed and connected";
+                                graph.replaceFloating((FloatingNode) node, canonical);
+                            }
+                        } else {
+                            assert node instanceof FixedWithNextNode && node.predecessor() != null : node + " -> " + canonical + " : node should be fixed & connected (" + node.predecessor() + ")";
+                            if (canonical == null) {
+                                // case 3
+                                graph.removeFixed((FixedWithNextNode) node);
+                            } else if (canonical instanceof FloatingNode) {
+                                // case 4
+                                graph.replaceFixedWithFloating((FixedWithNextNode) node, (FloatingNode) canonical);
+                            } else {
+                                assert canonical instanceof FixedNode;
+                                if (canonical.predecessor() == null) {
+                                    assert !canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " shouldn't have successors";
+                                    // case 5
+                                    graph.replaceFixedWithFixed((FixedWithNextNode) node, (FixedWithNextNode) canonical);
+                                } else {
+                                    assert canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " should have successors";
+                                    // case 6
+                                    node.replaceAtUsages(canonical);
+                                    graph.removeFixed((FixedWithNextNode) node);
+                                }
+                            }
+                        }
+                        return true;
+                    }
+                }
+            });
+        } else if (node instanceof Simplifiable) {
+            Debug.log("Canonicalizer: simplifying %s", node);
+            METRIC_SIMPLIFICATION_CONSIDERED_NODES.increment();
+            Debug.scope("SimplifyNode", node, new Runnable() {
+                public void run() {
+                    ((Simplifiable) node).simplify(tool);
+                }
+            });
+        }
+        return node.isDeleted();
+    }
+
+    /**
+     * Calls {@link ValueNode#inferStamp()} on the node and, if it returns true (which means that the stamp has
+     * changed), re-queues the node's usages . If the stamp has changed then this method also checks if the stamp
+     * now describes a constant integer value, in which case the node is replaced with a constant.
+     */
+    private void tryInferStamp(Node node, StructuredGraph graph) {
+        if (node.isAlive() && node instanceof ValueNode) {
+            ValueNode valueNode = (ValueNode) node;
+            METRIC_INFER_STAMP_CALLED.increment();
+            if (valueNode.inferStamp()) {
+                METRIC_STAMP_CHANGED.increment();
+                if (valueNode.stamp() instanceof IntegerStamp && valueNode.integerStamp().lowerBound() == valueNode.integerStamp().upperBound()) {
+                    ValueNode replacement = ConstantNode.forIntegerKind(valueNode.kind(), valueNode.integerStamp().lowerBound(), graph);
+                    Debug.log("Canonicalizer: replacing %s with %s (inferStamp)", valueNode, replacement);
+                    valueNode.replaceAtUsages(replacement);
+                } else {
+                    for (Node usage : valueNode.usages()) {
+                        workList.addAgain(usage);
+                    }
+                }
+            }
+        }
+    }
+
+    private static final class Tool implements SimplifierTool {
+
+        private final NodeWorkList nodeWorkSet;
+        private final MetaAccessProvider runtime;
+        private final TargetDescription target;
+        private final Assumptions assumptions;
+        private final IsImmutablePredicate immutabilityPredicate;
+
+        public Tool(NodeWorkList nodeWorkSet, MetaAccessProvider runtime, TargetDescription target, Assumptions assumptions, IsImmutablePredicate immutabilityPredicate) {
+            this.nodeWorkSet = nodeWorkSet;
+            this.runtime = runtime;
+            this.target = target;
+            this.assumptions = assumptions;
+            this.immutabilityPredicate = immutabilityPredicate;
+        }
+
+        @Override
+        public void deleteBranch(FixedNode branch) {
+            branch.predecessor().replaceFirstSuccessor(branch, null);
+            GraphUtil.killCFG(branch);
+        }
+
+        /**
+         * @return the current target or {@code null} if no target is available in the current context.
+         */
+        @Override
+        public TargetDescription target() {
+            return target;
+        }
+
+        /**
+         * @return an object that can be used for recording assumptions or {@code null} if assumptions are not allowed in the current context.
+         */
+        @Override
+        public Assumptions assumptions() {
+            return assumptions;
+        }
+
+        @Override
+        public MetaAccessProvider runtime() {
+            return runtime;
+        }
+
+        @Override
+        public void addToWorkList(Node node) {
+            nodeWorkSet.add(node);
+        }
+
+        @Override
+        public boolean isImmutable(Constant objectConstant) {
+            return immutabilityPredicate != null && immutabilityPredicate.apply(objectConstant);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/CheckCastEliminationPhase.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 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 com.oracle.graal.phases.phases;
+
+import java.util.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.phases.graph.*;
+
+public class CheckCastEliminationPhase extends Phase {
+
+    private static final DebugMetric metricInstanceOfRegistered = Debug.metric("InstanceOfRegistered");
+    private static final DebugMetric metricNullCheckRegistered = Debug.metric("NullCheckRegistered");
+    private static final DebugMetric metricCheckCastRemoved = Debug.metric("CheckCastRemoved");
+    private static final DebugMetric metricInstanceOfRemoved = Debug.metric("InstanceOfRemoved");
+    private static final DebugMetric metricNullCheckRemoved = Debug.metric("NullCheckRemoved");
+    private static final DebugMetric metricNullCheckGuardRemoved = Debug.metric("NullCheckGuardRemoved");
+    private static final DebugMetric metricGuardsReplaced = Debug.metric("GuardsReplaced");
+
+    private StructuredGraph graph;
+
+    @Override
+    protected void run(StructuredGraph inputGraph) {
+        graph = inputGraph;
+        new EliminateCheckCasts(graph.start(), new State()).apply();
+    }
+
+    public static class State implements MergeableState<State> {
+
+        private IdentityHashMap<ValueNode, ResolvedJavaType> knownTypes;
+        private HashSet<ValueNode> knownNotNull;
+        private HashSet<ValueNode> knownNull;
+        private IdentityHashMap<BooleanNode, ValueNode> trueConditions;
+        private IdentityHashMap<BooleanNode, ValueNode> falseConditions;
+
+        public State() {
+            this.knownTypes = new IdentityHashMap<>();
+            this.knownNotNull = new HashSet<>();
+            this.knownNull = new HashSet<>();
+            this.trueConditions = new IdentityHashMap<>();
+            this.falseConditions = new IdentityHashMap<>();
+        }
+
+        public State(State other) {
+            this.knownTypes = new IdentityHashMap<>(other.knownTypes);
+            this.knownNotNull = new HashSet<>(other.knownNotNull);
+            this.knownNull = new HashSet<>(other.knownNull);
+            this.trueConditions = new IdentityHashMap<>(other.trueConditions);
+            this.falseConditions = new IdentityHashMap<>(other.falseConditions);
+        }
+
+        @Override
+        public boolean merge(MergeNode merge, List<State> withStates) {
+            IdentityHashMap<ValueNode, ResolvedJavaType> newKnownTypes = new IdentityHashMap<>();
+            HashSet<ValueNode> newKnownNotNull = new HashSet<>();
+            HashSet<ValueNode> newKnownNull = new HashSet<>();
+            IdentityHashMap<BooleanNode, ValueNode> newTrueConditions = new IdentityHashMap<>();
+            IdentityHashMap<BooleanNode, ValueNode> newFalseConditions = new IdentityHashMap<>();
+
+            for (Map.Entry<ValueNode, ResolvedJavaType> entry : knownTypes.entrySet()) {
+                ValueNode node = entry.getKey();
+                ResolvedJavaType type = entry.getValue();
+
+                for (State other : withStates) {
+                    ResolvedJavaType otherType = other.getNodeType(node);
+                    type = widen(type, otherType);
+                    if (type == null) {
+                        break;
+                    }
+                }
+                if (type == null && type != node.objectStamp().type()) {
+                    newKnownTypes.put(node, type);
+                }
+            }
+            for (ValueNode node : knownNotNull) {
+                boolean notNull = true;
+                for (State other : withStates) {
+                    if (!other.knownNotNull.contains(node)) {
+                        notNull = false;
+                        break;
+                    }
+                }
+                if (notNull) {
+                    newKnownNotNull.add(node);
+                }
+            }
+            for (ValueNode node : knownNull) {
+                boolean nul = true;
+                for (State other : withStates) {
+                    if (!other.knownNull.contains(node)) {
+                        nul = false;
+                        break;
+                    }
+                }
+                if (nul) {
+                    newKnownNull.add(node);
+                }
+            }
+            for (Map.Entry<BooleanNode, ValueNode> entry : trueConditions.entrySet()) {
+                BooleanNode check = entry.getKey();
+                ValueNode guard = entry.getValue();
+
+                for (State other : withStates) {
+                    ValueNode otherGuard = other.trueConditions.get(check);
+                    if (otherGuard == null) {
+                        guard = null;
+                        break;
+                    }
+                    if (otherGuard != guard) {
+                        guard = merge;
+                    }
+                }
+                if (guard != null) {
+                    newTrueConditions.put(check, guard);
+                }
+            }
+            for (Map.Entry<BooleanNode, ValueNode> entry : falseConditions.entrySet()) {
+                BooleanNode check = entry.getKey();
+                ValueNode guard = entry.getValue();
+
+                for (State other : withStates) {
+                    ValueNode otherGuard = other.falseConditions.get(check);
+                    if (otherGuard == null) {
+                        guard = null;
+                        break;
+                    }
+                    if (otherGuard != guard) {
+                        guard = merge;
+                    }
+                }
+                if (guard != null) {
+                    newFalseConditions.put(check, guard);
+                }
+            }
+
+            /*
+            // this piece of code handles phis (merges the types and knownNull/knownNotNull of the values)
+            if (!(merge instanceof LoopBeginNode)) {
+                for (PhiNode phi : merge.phis()) {
+                    if (phi.type() == PhiType.Value && phi.kind() == Kind.Object) {
+                        ValueNode firstValue = phi.valueAt(0);
+                        ResolvedJavaType type = getNodeType(firstValue);
+                        boolean notNull = knownNotNull.contains(firstValue);
+                        boolean nul = knownNull.contains(firstValue);
+
+                        for (int i = 0; i < withStates.size(); i++) {
+                            State otherState = withStates.get(i);
+                            ValueNode value = phi.valueAt(i + 1);
+                            ResolvedJavaType otherType = otherState.getNodeType(value);
+                            type = widen(type, otherType);
+                            notNull &= otherState.knownNotNull.contains(value);
+                            nul &= otherState.knownNull.contains(value);
+                        }
+                        if (type == null && type != phi.declaredType()) {
+                            newKnownTypes.put(phi, type);
+                        }
+                        if (notNull) {
+                            newKnownNotNull.add(phi);
+                        }
+                        if (nul) {
+                            newKnownNull.add(phi);
+                        }
+                    }
+                }
+            }
+            */
+            this.knownTypes = newKnownTypes;
+            this.knownNotNull = newKnownNotNull;
+            this.knownNull = newKnownNull;
+            this.trueConditions = newTrueConditions;
+            this.falseConditions = newFalseConditions;
+            return true;
+        }
+
+        public ResolvedJavaType getNodeType(ValueNode node) {
+            ResolvedJavaType result = knownTypes.get(node);
+            return result == null ? node.objectStamp().type() : result;
+        }
+
+        @Override
+        public void loopBegin(LoopBeginNode loopBegin) {
+        }
+
+        @Override
+        public void loopEnds(LoopBeginNode loopBegin, List<State> loopEndStates) {
+        }
+
+        @Override
+        public void afterSplit(FixedNode node) {
+        }
+
+        @Override
+        public State clone() {
+            return new State(this);
+        }
+    }
+
+    public static ResolvedJavaType widen(ResolvedJavaType a, ResolvedJavaType b) {
+        if (a == null || b == null) {
+            return null;
+        } else if (a == b) {
+            return a;
+        } else {
+            return a.leastCommonAncestor(b);
+        }
+    }
+
+    public static ResolvedJavaType tighten(ResolvedJavaType a, ResolvedJavaType b) {
+        if (a == null) {
+            return b;
+        } else if (b == null) {
+            return a;
+        } else if (a == b) {
+            return a;
+        } else if (a.isSubtypeOf(b)) {
+            return a;
+        } else if (b.isSubtypeOf(a)) {
+            return b;
+        } else {
+            return a;
+        }
+    }
+
+    public class EliminateCheckCasts extends PostOrderNodeIterator<State> {
+        private BeginNode lastBegin = null;
+
+        public EliminateCheckCasts(FixedNode start, State initialState) {
+            super(start, initialState);
+        }
+
+        @Override
+        protected void node(FixedNode node) {
+            if (node instanceof BeginNode) {
+                BeginNode begin = (BeginNode) node;
+                lastBegin = begin;
+                Node pred = node.predecessor();
+                if (pred != null && pred instanceof IfNode) {
+                    IfNode ifNode = (IfNode) pred;
+                    if (!(ifNode.compare() instanceof ConstantNode)) {
+                        boolean isTrue = (node == ifNode.trueSuccessor());
+                        if (isTrue) {
+                            state.trueConditions.put(ifNode.compare(), begin);
+                        } else {
+                            state.falseConditions.put(ifNode.compare(), begin);
+                        }
+                    }
+                    if (ifNode.compare() instanceof InstanceOfNode) {
+                        InstanceOfNode instanceOf = (InstanceOfNode) ifNode.compare();
+                        if ((node == ifNode.trueSuccessor())) {
+                            ValueNode object = instanceOf.object();
+                            state.knownNotNull.add(object);
+                            state.knownTypes.put(object, tighten(instanceOf.targetClass(), state.getNodeType(object)));
+                            metricInstanceOfRegistered.increment();
+                        }
+                    } else if (ifNode.compare() instanceof IsNullNode) {
+                        IsNullNode nullCheck = (IsNullNode) ifNode.compare();
+                        boolean isNull = (node == ifNode.trueSuccessor());
+                        if (isNull) {
+                            state.knownNull.add(nullCheck.object());
+                        } else {
+                            state.knownNotNull.add(nullCheck.object());
+                        }
+                        metricNullCheckRegistered.increment();
+                    }
+                }
+                for (GuardNode guard : begin.guards().snapshot()) {
+                    BooleanNode condition = guard.condition();
+                    ValueNode existingGuards = guard.negated() ? state.falseConditions.get(condition) : state.trueConditions.get(condition);
+                    if (existingGuards != null) {
+                        guard.replaceAtUsages(existingGuards);
+                        GraphUtil.killWithUnusedFloatingInputs(guard);
+                        metricGuardsReplaced.increment();
+                    } else {
+                        boolean removeCheck = false;
+                        if (condition instanceof IsNullNode) {
+                            IsNullNode isNull = (IsNullNode) condition;
+                            if (guard.negated() && state.knownNotNull.contains(isNull.object())) {
+                                removeCheck = true;
+                            } else if (!guard.negated() && state.knownNull.contains(isNull.object())) {
+                                removeCheck = true;
+                            }
+                            if (removeCheck) {
+                                metricNullCheckGuardRemoved.increment();
+                            }
+                        }
+                        if (removeCheck) {
+                            guard.replaceAtUsages(begin);
+                            GraphUtil.killWithUnusedFloatingInputs(guard);
+                        } else {
+                            if (guard.negated()) {
+                                state.falseConditions.put(condition, guard);
+                            } else {
+                                state.trueConditions.put(condition, guard);
+                            }
+                        }
+                    }
+                }
+            } else if (node instanceof CheckCastNode) {
+                CheckCastNode checkCast = (CheckCastNode) node;
+                ResolvedJavaType type = state.getNodeType(checkCast.object());
+                if (checkCast.targetClass() != null && type != null && type.isSubtypeOf(checkCast.targetClass())) {
+                    PiNode piNode;
+                    boolean nonNull = state.knownNotNull.contains(checkCast.object());
+                    piNode = graph.unique(new PiNode(checkCast.object(), lastBegin, nonNull ? StampFactory.declaredNonNull(type) : StampFactory.declared(type)));
+                    checkCast.replaceAtUsages(piNode);
+                    graph.removeFixed(checkCast);
+                    metricCheckCastRemoved.increment();
+                }
+            } else if (node instanceof IfNode) {
+                IfNode ifNode = (IfNode) node;
+                BooleanNode replaceWith = null;
+                BooleanNode compare = ifNode.compare();
+
+                if (state.trueConditions.containsKey(compare)) {
+                    replaceWith = ConstantNode.forBoolean(true, graph);
+                } else if (state.falseConditions.containsKey(compare)) {
+                    replaceWith = ConstantNode.forBoolean(false, graph);
+                } else {
+                    if (compare instanceof InstanceOfNode) {
+                        InstanceOfNode instanceOf = (InstanceOfNode) compare;
+                        ValueNode object = instanceOf.object();
+                        if (state.knownNull.contains(object)) {
+                            replaceWith = ConstantNode.forBoolean(false, graph);
+                        } else if (state.knownNotNull.contains(object)) {
+                            ResolvedJavaType type = state.getNodeType(object);
+                            if (type != null && type.isSubtypeOf(instanceOf.targetClass())) {
+                                replaceWith = ConstantNode.forBoolean(true, graph);
+                            }
+                        }
+                        if (replaceWith != null) {
+                            metricInstanceOfRemoved.increment();
+                        }
+                    } else if (compare instanceof IsNullNode) {
+                        IsNullNode isNull = (IsNullNode) compare;
+                        ValueNode object = isNull.object();
+                        if (state.knownNull.contains(object)) {
+                            replaceWith = ConstantNode.forBoolean(true, graph);
+                        } else if (state.knownNotNull.contains(object)) {
+                            replaceWith = ConstantNode.forBoolean(false, graph);
+                        }
+                        if (replaceWith != null) {
+                            metricNullCheckRemoved.increment();
+                        }
+                    }
+                }
+                if (replaceWith != null) {
+                    ifNode.setCompare(replaceWith);
+                    if (compare.usages().isEmpty()) {
+                        GraphUtil.killWithUnusedFloatingInputs(compare);
+                    }
+                }
+            }
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/ComputeProbabilityPhase.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,372 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.phases.phases;
+
+import java.util.*;
+
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.cfg.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.graph.*;
+
+public class ComputeProbabilityPhase extends Phase {
+    private static final double EPSILON = 1d / Integer.MAX_VALUE;
+
+    /*
+     * The computation of absolute probabilities works in three steps:
+     *
+     * - The first step, "PropagateProbability", traverses the graph in post order (merges after their ends, ...) and keeps track of the "probability state".
+     *   Whenever it encounters a ControlSplit it uses the split's probability information to divide the probability upon the successors.
+     *   Whenever it encounters an Invoke it assumes that the exception edge is unlikely and propagates the whole probability to the normal successor.
+     *   Whenever it encounters a Merge it sums up the probability of all predecessors.
+     *   It also maintains a set of active loops (whose LoopBegin has been visited) and builds def/use information for the second step.
+     *
+     * - The third step propagates the loop frequencies and multiplies each FixedNode's probability with its loop frequency.
+     *
+     *   TODO: add exception probability information to Invokes
+     */
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        new PropagateProbability(graph.start()).apply();
+        Debug.dump(graph, "After PropagateProbability");
+        computeLoopFactors();
+        Debug.dump(graph, "After computeLoopFactors");
+        new PropagateLoopFrequency(graph.start()).apply();
+
+        if (GraalOptions.LoopFrequencyPropagationPolicy < 0) {
+            ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, false, false);
+            BitSet visitedBlocks = new BitSet(cfg.getBlocks().length);
+            for (Loop loop : cfg.getLoops()) {
+                if (loop.parent == null) {
+                    correctLoopFrequencies(loop, 1, visitedBlocks);
+                }
+            }
+        }
+    }
+
+    private void correctLoopFrequencies(Loop loop, double parentFrequency, BitSet visitedBlocks) {
+        LoopBeginNode loopBegin = ((LoopBeginNode) loop.header.getBeginNode());
+        double frequency = parentFrequency * loopBegin.loopFrequency();
+        for (Loop child : loop.children) {
+            correctLoopFrequencies(child, frequency, visitedBlocks);
+        }
+
+        double factor = getCorrectionFactor(loopBegin.probability(), frequency);
+        for (Block block : loop.blocks) {
+            int blockId = block.getId();
+            if (!visitedBlocks.get(blockId)) {
+                visitedBlocks.set(blockId);
+
+                FixedNode node = block.getBeginNode();
+                while (node != block.getEndNode()) {
+                    node.setProbability(node.probability() * factor);
+                    node = ((FixedWithNextNode) node).next();
+                }
+                node.setProbability(node.probability() * factor);
+            }
+        }
+    }
+
+    private static double getCorrectionFactor(double probability, double frequency) {
+        switch (GraalOptions.LoopFrequencyPropagationPolicy) {
+            case -1:
+                return 1 / frequency;
+            case -2:
+                return (1 / frequency) * (Math.log(Math.E + frequency) - 1);
+            case -3:
+                double originalProbability = probability / frequency;
+                assert isRelativeProbability(originalProbability);
+                return (1 / frequency) * Math.max(1, Math.pow(originalProbability, 1.5) * Math.log10(frequency));
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    private void computeLoopFactors() {
+        for (LoopInfo info : loopInfos) {
+            double frequency = info.loopFrequency();
+            assert frequency != -1;
+        }
+    }
+
+    private static boolean isRelativeProbability(double prob) {
+        // 1.01 to allow for some rounding errors
+        return prob >= 0 && prob <= 1.01;
+    }
+
+    public static class LoopInfo {
+        public final LoopBeginNode loopBegin;
+
+        public final NodeMap<Set<LoopInfo>> requires;
+
+        private double loopFrequency = -1;
+        public boolean ended = false;
+
+        public LoopInfo(LoopBeginNode loopBegin) {
+            this.loopBegin = loopBegin;
+            this.requires = loopBegin.graph().createNodeMap();
+        }
+
+        public double loopFrequency() {
+            if (loopFrequency == -1 && ended) {
+                double backEdgeProb = 0.0;
+                for (LoopEndNode le : loopBegin.loopEnds()) {
+                    double factor = 1;
+                    Set<LoopInfo> requireds = requires.get(le);
+                    for (LoopInfo required : requireds) {
+                        double t = required.loopFrequency();
+                        if (t == -1) {
+                            return -1;
+                        }
+                        factor *= t;
+                    }
+                    backEdgeProb += le.probability() * factor;
+                }
+                double d = loopBegin.probability() - backEdgeProb;
+                if (d < EPSILON) {
+                    d = EPSILON;
+                }
+                loopFrequency = loopBegin.probability() / d;
+                loopBegin.setLoopFrequency(loopFrequency);
+            }
+            return loopFrequency;
+        }
+    }
+
+    public Set<LoopInfo> loopInfos = new HashSet<>();
+    public Map<MergeNode, Set<LoopInfo>> mergeLoops = new IdentityHashMap<>();
+
+    private class Probability implements MergeableState<Probability> {
+        public double probability;
+        public HashSet<LoopInfo> loops;
+        public LoopInfo loopInfo;
+
+        public Probability(double probability, HashSet<LoopInfo> loops) {
+            this.probability = probability;
+            this.loops = new HashSet<>(4);
+            if (loops != null) {
+                this.loops.addAll(loops);
+            }
+        }
+
+        @Override
+        public Probability clone() {
+            return new Probability(probability, loops);
+        }
+
+        @Override
+        public boolean merge(MergeNode merge, List<Probability> withStates) {
+            if (merge.forwardEndCount() > 1) {
+                HashSet<LoopInfo> intersection = new HashSet<>(loops);
+                for (Probability other : withStates) {
+                    intersection.retainAll(other.loops);
+                }
+                for (LoopInfo info : loops) {
+                    if (!intersection.contains(info)) {
+                        double loopFrequency = info.loopFrequency();
+                        if (loopFrequency == -1) {
+                            return false;
+                        }
+                        probability *= loopFrequency;
+                    }
+                }
+                for (Probability other : withStates) {
+                    double prob = other.probability;
+                    for (LoopInfo info : other.loops) {
+                        if (!intersection.contains(info)) {
+                            double loopFrequency = info.loopFrequency();
+                            if (loopFrequency == -1) {
+                                return false;
+                            }
+                            prob *= loopFrequency;
+                        }
+                    }
+                    probability += prob;
+                }
+                loops = intersection;
+                mergeLoops.put(merge, new HashSet<>(intersection));
+                assert isRelativeProbability(probability) : probability;
+            }
+            return true;
+        }
+
+        @Override
+        public void loopBegin(LoopBeginNode loopBegin) {
+            loopInfo = new LoopInfo(loopBegin);
+            loopInfos.add(loopInfo);
+            loops.add(loopInfo);
+        }
+
+        @Override
+        public void loopEnds(LoopBeginNode loopBegin, List<Probability> loopEndStates) {
+            assert loopInfo != null;
+            List<LoopEndNode> loopEnds = loopBegin.orderedLoopEnds();
+            int i = 0;
+            for (Probability proba : loopEndStates) {
+                LoopEndNode loopEnd = loopEnds.get(i++);
+                Set<LoopInfo> requires = loopInfo.requires.get(loopEnd);
+                if (requires == null) {
+                    requires = new HashSet<>();
+                    loopInfo.requires.set(loopEnd, requires);
+                }
+                for (LoopInfo innerLoop : proba.loops) {
+                    if (innerLoop != loopInfo && !this.loops.contains(innerLoop)) {
+                        requires.add(innerLoop);
+                    }
+                }
+            }
+            loopInfo.ended = true;
+        }
+
+        @Override
+        public void afterSplit(FixedNode node) {
+            assert node.predecessor() != null;
+            Node pred = node.predecessor();
+            if (pred instanceof Invoke) {
+                Invoke x = (Invoke) pred;
+                if (x.next() != node) {
+                    probability = 0;
+                }
+            } else {
+                assert pred instanceof ControlSplitNode;
+                ControlSplitNode x = (ControlSplitNode) pred;
+                double sum = 0;
+                for (int i = 0; i < x.blockSuccessorCount(); i++) {
+                    if (x.blockSuccessor(i) == node) {
+                        sum += x.probability(i);
+                    }
+                }
+                probability *= sum;
+            }
+        }
+    }
+
+    private class PropagateProbability extends PostOrderNodeIterator<Probability> {
+
+        public PropagateProbability(FixedNode start) {
+            super(start, new Probability(1d, null));
+        }
+
+        @Override
+        protected void node(FixedNode node) {
+            node.setProbability(state.probability);
+        }
+    }
+
+    private class LoopCount implements MergeableState<LoopCount> {
+        public double count;
+
+        public LoopCount(double count) {
+            this.count = count;
+        }
+
+        @Override
+        public LoopCount clone() {
+            return new LoopCount(count);
+        }
+
+        @Override
+        public boolean merge(MergeNode merge, List<LoopCount> withStates) {
+            assert merge.forwardEndCount() == withStates.size() + 1;
+            if (merge.forwardEndCount() > 1) {
+                Set<LoopInfo> loops = mergeLoops.get(merge);
+                assert loops != null;
+                double countProd = 1;
+                for (LoopInfo loop : loops) {
+                    countProd *= loop.loopFrequency();
+                }
+                count = countProd;
+            }
+            return true;
+        }
+
+        @Override
+        public void loopBegin(LoopBeginNode loopBegin) {
+            count *= loopBegin.loopFrequency();
+        }
+
+        @Override
+        public void loopEnds(LoopBeginNode loopBegin, List<LoopCount> loopEndStates) {
+            // nothing to do...
+        }
+
+        @Override
+        public void afterSplit(FixedNode node) {
+            // nothing to do...
+        }
+    }
+
+    private class PropagateLoopFrequency extends PostOrderNodeIterator<LoopCount> {
+
+        private final FrequencyPropagationPolicy policy;
+
+        public PropagateLoopFrequency(FixedNode start) {
+            super(start, new LoopCount(1d));
+            this.policy = createFrequencyPropagationPolicy();
+        }
+
+        @Override
+        protected void node(FixedNode node) {
+            node.setProbability(policy.compute(node.probability(), state.count));
+        }
+
+    }
+
+    private static FrequencyPropagationPolicy createFrequencyPropagationPolicy() {
+        switch (GraalOptions.LoopFrequencyPropagationPolicy) {
+            case -3:
+            case -2:
+            case -1:
+            case 0:
+                return new FullFrequencyPropagation();
+            case 1:
+                return new NoFrequencyPropagation();
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    private interface FrequencyPropagationPolicy {
+
+        double compute(double probability, double frequency);
+    }
+
+    private static class FullFrequencyPropagation implements FrequencyPropagationPolicy {
+
+        @Override
+        public double compute(double probability, double frequency) {
+            return probability * frequency;
+        }
+    }
+
+    private static class NoFrequencyPropagation implements FrequencyPropagationPolicy {
+
+        @Override
+        public double compute(double probability, double frequency) {
+            return probability;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/ConvertDeoptimizeToGuardPhase.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.phases.phases;
+
+import java.util.*;
+
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.util.*;
+
+public class ConvertDeoptimizeToGuardPhase extends Phase {
+
+    private static BeginNode findBeginNode(Node startNode) {
+        Node n = startNode;
+        while (true) {
+            if (n instanceof BeginNode) {
+                return (BeginNode) n;
+            } else {
+                n = n.predecessor();
+            }
+        }
+    }
+
+    @Override
+    protected void run(final StructuredGraph graph) {
+        if (graph.getNodes(DeoptimizeNode.class).isEmpty()) {
+            return;
+        }
+
+        for (DeoptimizeNode d : graph.getNodes(DeoptimizeNode.class)) {
+            visitDeoptBegin(findBeginNode(d), d, graph);
+        }
+
+        new DeadCodeEliminationPhase().apply(graph);
+    }
+
+    private void visitDeoptBegin(BeginNode deoptBegin, DeoptimizeNode deopt, StructuredGraph graph) {
+        if (deoptBegin instanceof MergeNode) {
+            MergeNode mergeNode = (MergeNode) deoptBegin;
+            Debug.log("Visiting %s followed by %s", mergeNode, deopt);
+            List<EndNode> ends = mergeNode.forwardEnds().snapshot();
+            for (EndNode end : ends) {
+                if (!end.isDeleted()) {
+                    BeginNode beginNode = findBeginNode(end);
+                    if (!(beginNode instanceof MergeNode)) {
+                        visitDeoptBegin(beginNode, deopt, graph);
+                    }
+                }
+            }
+            if (mergeNode.isDeleted()) {
+                if (!deopt.isDeleted()) {
+                    Debug.log("Merge deleted, deopt moved to %s", findBeginNode(deopt));
+                    visitDeoptBegin(findBeginNode(deopt), deopt, graph);
+                }
+            }
+        } else if (deoptBegin.predecessor() instanceof IfNode) {
+            IfNode ifNode = (IfNode) deoptBegin.predecessor();
+            BeginNode otherBegin = ifNode.trueSuccessor();
+            BooleanNode conditionNode = ifNode.compare();
+            boolean negated = false;
+            if (deoptBegin == ifNode.trueSuccessor()) {
+                negated = true;
+                otherBegin = ifNode.falseSuccessor();
+            }
+            BeginNode ifBlockBegin = findBeginNode(ifNode);
+            Debug.log("Converting %s on %-5s branch of %s to guard for remaining branch %s. IfBegin=%s", deopt, deoptBegin == ifNode.trueSuccessor() ? "true" : "false", ifNode, otherBegin, ifBlockBegin);
+            FixedGuardNode guard = graph.add(new FixedGuardNode(conditionNode, deopt.reason(), deopt.action(), negated, deopt.leafGraphId()));
+            otherBegin.replaceAtUsages(ifBlockBegin);
+            FixedNode next = otherBegin.next();
+            otherBegin.setNext(null);
+            guard.setNext(next);
+            ifNode.replaceAtPredecessor(guard);
+            GraphUtil.killCFG(ifNode);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/ConvertUnreachedToGuardPhase.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 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 com.oracle.graal.phases.phases;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.phases.*;
+
+
+public class ConvertUnreachedToGuardPhase extends Phase {
+    private OptimisticOptimizations opt;
+
+    public ConvertUnreachedToGuardPhase(OptimisticOptimizations opt) {
+        this.opt = opt;
+    }
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        if (!opt.removeNeverExecutedCode()) {
+            return;
+        }
+        for (Node node : graph.getNodes()) {
+            if (node instanceof IfNode) {
+                IfNode ifNode = (IfNode) node;
+                BeginNode insertGuard = null;
+                BeginNode delete = null;
+                boolean inverted = false;
+                if (ifNode.probability(IfNode.TRUE_EDGE) == 0) {
+                    insertGuard = ifNode.falseSuccessor();
+                    delete = ifNode.trueSuccessor();
+                    inverted = true;
+                } else if (ifNode.probability(IfNode.FALSE_EDGE) == 0) {
+                    insertGuard = ifNode.trueSuccessor();
+                    delete = ifNode.falseSuccessor();
+                }
+                if (insertGuard != null) {
+                    GuardNode guard = graph.unique(new GuardNode(ifNode.compare(), BeginNode.prevBegin(ifNode), DeoptimizationReason.UnreachedCode, DeoptimizationAction.InvalidateReprofile, inverted, ifNode.leafGraphId()));
+                    graph.addBeforeFixed(ifNode, graph.add(new ValueAnchorNode(guard)));
+                    GraphUtil.killCFG(delete);
+                    graph.removeSplit(ifNode, inverted ? IfNode.FALSE_EDGE : IfNode.TRUE_EDGE);
+                }
+            }
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/CullFrameStatesPhase.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 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 com.oracle.graal.phases.phases;
+
+import java.util.*;
+
+import com.oracle.graal.debug.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.phases.graph.*;
+
+/**
+ * This phase culls unused FrameStates from the graph.
+ * It does a post order iteration over the graph, and
+ */
+public class CullFrameStatesPhase extends Phase {
+
+    private static final DebugMetric metricFrameStatesCulled = Debug.metric("FrameStatesCulled");
+    private static final DebugMetric metricMergesTraversed = Debug.metric("MergesTraversed");
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        new CullFrameStates(graph.start(), new State(null)).apply();
+    }
+
+    public static class State implements MergeableState<State> {
+
+        private FrameState lastFrameState;
+
+        public State(FrameState lastFrameState) {
+            this.lastFrameState = lastFrameState;
+        }
+
+        @Override
+        public boolean merge(MergeNode merge, List<State> withStates) {
+            FrameState stateAfter = merge.stateAfter();
+            if (merge instanceof LoopBeginNode) {
+                if (stateAfter != null) {
+                    lastFrameState = stateAfter;
+                }
+                return true;
+            }
+            metricMergesTraversed.increment();
+            if (stateAfter != null) {
+                for (State other : withStates) {
+                    if (other.lastFrameState != lastFrameState) {
+                        lastFrameState = stateAfter;
+                        return true;
+                    }
+                }
+                metricFrameStatesCulled.increment();
+                merge.setStateAfter(null);
+                if (stateAfter.usages().isEmpty()) {
+                    GraphUtil.killWithUnusedFloatingInputs(stateAfter);
+                }
+            }
+            return true;
+        }
+
+        @Override
+        public void loopBegin(LoopBeginNode loopBegin) {
+        }
+
+        @Override
+        public void loopEnds(LoopBeginNode loopBegin, List<State> loopEndStates) {
+        }
+
+        @Override
+        public void afterSplit(FixedNode node) {
+        }
+
+        @Override
+        public State clone() {
+            return new State(lastFrameState);
+        }
+    }
+
+    public static class CullFrameStates extends PostOrderNodeIterator<State> {
+
+        public CullFrameStates(FixedNode start, State initialState) {
+            super(start, initialState);
+        }
+
+        @Override
+        protected void node(FixedNode node) {
+            if (node instanceof StateSplit) {
+                FrameState stateAfter = ((StateSplit) node).stateAfter();
+                if (stateAfter != null) {
+                    state.lastFrameState = stateAfter;
+                }
+            }
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/DeadCodeEliminationPhase.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.phases.phases;
+
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+
+
+public class DeadCodeEliminationPhase extends Phase {
+
+    // Metrics
+    private static final DebugMetric metricNodesRemoved = Debug.metric("NodesRemoved");
+
+    private NodeFlood flood;
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        this.flood = graph.createNodeFlood();
+
+        flood.add(graph.start());
+        iterateSuccessors();
+        disconnectCFGNodes(graph);
+        iterateInputs(graph);
+        deleteNodes(graph);
+
+        // remove chained Merges
+        for (MergeNode merge : graph.getNodes(MergeNode.class)) {
+            if (merge.forwardEndCount() == 1 && !(merge instanceof LoopBeginNode)) {
+                graph.reduceTrivialMerge(merge);
+            }
+        }
+    }
+
+    private void iterateSuccessors() {
+        for (Node current : flood) {
+            if (current instanceof EndNode) {
+                EndNode end = (EndNode) current;
+                flood.add(end.merge());
+            } else {
+                for (Node successor : current.successors()) {
+                    flood.add(successor);
+                }
+            }
+        }
+    }
+
+    private void disconnectCFGNodes(StructuredGraph graph) {
+        for (EndNode node : graph.getNodes(EndNode.class)) {
+            if (!flood.isMarked(node)) {
+                MergeNode merge = node.merge();
+                if (merge != null && flood.isMarked(merge)) {
+                    // We are a dead end node leading to a live merge.
+                    merge.removeEnd(node);
+                }
+            }
+        }
+        for (LoopBeginNode loop : graph.getNodes(LoopBeginNode.class)) {
+            if (flood.isMarked(loop)) {
+                boolean reachable = false;
+                for (LoopEndNode end : loop.loopEnds()) {
+                    if (flood.isMarked(end)) {
+                        reachable = true;
+                        break;
+                    }
+                }
+                if (!reachable) {
+                    Debug.log("Removing loop with unreachable end: %s", loop);
+                    for (LoopEndNode end : loop.loopEnds().snapshot()) {
+                        loop.removeEnd(end);
+                    }
+                    graph.reduceDegenerateLoopBegin(loop);
+                }
+            }
+        }
+    }
+
+    private void deleteNodes(StructuredGraph graph) {
+        for (Node node : graph.getNodes()) {
+            if (!flood.isMarked(node)) {
+                node.clearInputs();
+                node.clearSuccessors();
+            }
+        }
+        for (Node node : graph.getNodes()) {
+            if (!flood.isMarked(node)) {
+                metricNodesRemoved.increment();
+                node.safeDelete();
+            }
+        }
+    }
+
+    private void iterateInputs(StructuredGraph graph) {
+        for (Node node : graph.getNodes()) {
+            if (node instanceof LocalNode) {
+                flood.add(node);
+            }
+            if (flood.isMarked(node)) {
+                for (Node input : node.inputs()) {
+                    flood.add(input);
+                }
+            }
+        }
+        for (Node current : flood) {
+            for (Node input : current.inputs()) {
+                flood.add(input);
+            }
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/ExpandBoxingNodesPhase.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.phases.phases;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+
+public class ExpandBoxingNodesPhase extends Phase {
+
+    private final BoxingMethodPool pool;
+
+    public ExpandBoxingNodesPhase(BoxingMethodPool pool) {
+        this.pool = pool;
+    }
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        for (BoxNode boxNode : graph.getNodes(BoxNode.class)) {
+            boxNode.expand(pool);
+        }
+
+        for (UnboxNode unboxNode : graph.getNodes(UnboxNode.class)) {
+            unboxNode.expand(pool);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/FloatingReadPhase.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,294 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.phases.phases;
+
+import java.util.*;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.PhiNode.PhiType;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.phases.graph.*;
+
+public class FloatingReadPhase extends Phase {
+
+    private IdentityHashMap<LoopBeginNode, List<MemoryMap>> loopEndStatesMap;
+
+    private static class LoopState {
+        public LoopBeginNode loopBegin;
+        public MemoryMap state;
+        public IdentityHashMap<PhiNode, Object> loopPhiLocations = new IdentityHashMap<>();
+        public ValueNode loopEntryAnyLocation;
+        public LoopState(LoopBeginNode loopBegin, MemoryMap state, ValueNode loopEntryAnyLocation) {
+            this.loopBegin = loopBegin;
+            this.state = state;
+            this.loopEntryAnyLocation = loopEntryAnyLocation;
+        }
+
+        @Override
+        public String toString() {
+            return "State@" + loopBegin;
+        }
+    }
+
+    private class MemoryMap implements MergeableState<MemoryMap> {
+        private IdentityHashMap<Object, ValueNode> lastMemorySnapshot;
+        private LinkedList<LoopState> loops;
+
+        public MemoryMap(MemoryMap memoryMap) {
+            lastMemorySnapshot = new IdentityHashMap<>(memoryMap.lastMemorySnapshot);
+            loops = new LinkedList<>(memoryMap.loops);
+        }
+
+        public MemoryMap() {
+            lastMemorySnapshot = new IdentityHashMap<>();
+            loops = new LinkedList<>();
+        }
+
+        @Override
+        public String toString() {
+            return "Map=" + lastMemorySnapshot.toString() + " Loops=" + loops.toString();
+        }
+
+        @Override
+        public boolean merge(MergeNode merge, List<MemoryMap> withStates) {
+            if (withStates.size() == 0) {
+                return true;
+            }
+
+            int minLoops = loops.size();
+            for (MemoryMap other : withStates) {
+                int otherLoops = other.loops.size();
+                if (otherLoops < minLoops) {
+                    minLoops = otherLoops;
+                }
+            }
+            while (loops.size() > minLoops) {
+                loops.pop();
+            }
+            for (MemoryMap other : withStates) {
+                while (other.loops.size() > minLoops) {
+                    other.loops.pop();
+                }
+            }
+
+            Set<Object> keys = new HashSet<>();
+            for (Object key : lastMemorySnapshot.keySet()) {
+                keys.add(key);
+            }
+            for (MemoryMap other : withStates) {
+                assert other.loops.size() == loops.size();
+                assert other.loops.size() < 1 || other.loops.peek().loopBegin == loops.peek().loopBegin;
+                for (Object key : other.lastMemorySnapshot.keySet()) {
+                    keys.add(key);
+                }
+            }
+            @SuppressWarnings("unchecked")
+            IdentityHashMap<Object, ValueNode> newMemorySnapshot = (IdentityHashMap<Object, ValueNode>) lastMemorySnapshot.clone();
+
+            for (Object key : keys) {
+                ValueNode merged = lastMemorySnapshot.get(key);
+                if (merged == null) {
+                    merged = lastMemorySnapshot.get(LocationNode.ANY_LOCATION);
+                }
+                int mergedStatesCount = 1;
+                boolean isPhi = false;
+                for (MemoryMap other : withStates) {
+                    ValueNode otherValue = other.lastMemorySnapshot.get(key);
+                    if (otherValue == null) {
+                        otherValue = other.lastMemorySnapshot.get(LocationNode.ANY_LOCATION);
+                    }
+                    if (isPhi) {
+                        ((PhiNode) merged).addInput(otherValue);
+                    } else if (merged != otherValue) {
+                        PhiNode phi = merge.graph().add(new PhiNode(PhiType.Memory, merge));
+                        for (int j = 0; j < mergedStatesCount; j++) {
+                            phi.addInput(merged);
+                        }
+                        phi.addInput(otherValue);
+                        merged = phi;
+                        isPhi = true;
+                        newMemorySnapshot.put(key, phi);
+                    }
+                    mergedStatesCount++;
+                }
+            }
+
+            lastMemorySnapshot = newMemorySnapshot;
+            return true;
+        }
+
+        @Override
+        public void loopBegin(LoopBeginNode loopBegin) {
+            LoopState loopState = new LoopState(loopBegin, this, lastMemorySnapshot.get(LocationNode.ANY_LOCATION));
+            for (Map.Entry<Object, ValueNode> entry : lastMemorySnapshot.entrySet()) {
+                PhiNode phi = loopBegin.graph().add(new PhiNode(PhiType.Memory, loopBegin));
+                phi.addInput(entry.getValue());
+                entry.setValue(phi);
+                loopState.loopPhiLocations.put(phi, entry.getKey());
+            }
+            loops.push(loopState);
+        }
+
+        @Override
+        public void loopEnds(LoopBeginNode loopBegin, List<MemoryMap> loopEndStates) {
+            loopEndStatesMap.put(loopBegin, loopEndStates);
+            tryFinishLoopPhis(this, loopBegin);
+        }
+
+        @Override
+        public void afterSplit(FixedNode node) {
+            // nothing
+        }
+
+        @Override
+        public MemoryMap clone() {
+            return new MemoryMap(this);
+        }
+    }
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        loopEndStatesMap = new IdentityHashMap<>();
+        new PostOrderNodeIterator<MemoryMap>(graph.start(), new MemoryMap()) {
+            @Override
+            protected void node(FixedNode node) {
+                processNode(node, state);
+            }
+        }.apply();
+    }
+
+    private void processNode(FixedNode node, MemoryMap state) {
+        if (node instanceof ReadNode) {
+            processRead((ReadNode) node, state);
+        } else if (node instanceof WriteNode) {
+            processWrite((WriteNode) node, state);
+        } else if (node instanceof MemoryCheckpoint) {
+            processCheckpoint((MemoryCheckpoint) node, state);
+        } else if (node instanceof LoopExitNode) {
+            processLoopExit((LoopExitNode) node, state);
+        }
+    }
+
+    private static void processCheckpoint(MemoryCheckpoint checkpoint, MemoryMap state) {
+        processAnyLocationWrite((ValueNode) checkpoint, state);
+    }
+
+    private static void processWrite(WriteNode writeNode, MemoryMap state) {
+        if (writeNode.location().locationIdentity() == LocationNode.ANY_LOCATION) {
+            processAnyLocationWrite(writeNode, state);
+        }
+        state.lastMemorySnapshot.put(writeNode.location().locationIdentity(), writeNode);
+    }
+
+    private static void processAnyLocationWrite(ValueNode modifiying, MemoryMap state) {
+        for (Map.Entry<Object, ValueNode> entry : state.lastMemorySnapshot.entrySet()) {
+            entry.setValue(modifiying);
+        }
+        state.lastMemorySnapshot.put(LocationNode.ANY_LOCATION, modifiying);
+        state.loops.clear();
+    }
+
+    private void processRead(ReadNode readNode, MemoryMap state) {
+        StructuredGraph graph = (StructuredGraph) readNode.graph();
+        assert readNode.getNullCheck() == false;
+        Object locationIdentity = readNode.location().locationIdentity();
+        ValueNode lastLocationAccess = getLastLocationAccessForRead(state, locationIdentity);
+        FloatingReadNode floatingRead = graph.unique(new FloatingReadNode(readNode.object(), readNode.location(), lastLocationAccess, readNode.stamp(), readNode.dependencies()));
+        floatingRead.setNullCheck(readNode.getNullCheck());
+        ValueAnchorNode anchor = null;
+        for (GuardNode guard : readNode.dependencies().filter(GuardNode.class)) {
+            if (anchor == null) {
+                anchor = graph.add(new ValueAnchorNode());
+            }
+            anchor.addAnchoredNode(guard);
+        }
+        if (anchor != null) {
+            graph.addAfterFixed(readNode, anchor);
+        }
+        graph.replaceFixedWithFloating(readNode, floatingRead);
+    }
+
+    private ValueNode getLastLocationAccessForRead(MemoryMap state, Object locationIdentity) {
+        ValueNode lastLocationAccess;
+        if (locationIdentity == LocationNode.FINAL_LOCATION) {
+            lastLocationAccess = null;
+        } else {
+            lastLocationAccess = state.lastMemorySnapshot.get(locationIdentity);
+            if (lastLocationAccess == null) {
+                LoopState lastLoop = state.loops.peek();
+                if (lastLoop == null) {
+                    lastLocationAccess = state.lastMemorySnapshot.get(LocationNode.ANY_LOCATION);
+                } else {
+                    ValueNode phiInit;
+                    if (state.loops.size() > 1) {
+                        phiInit = getLastLocationAccessForRead(state.loops.get(1).state, locationIdentity);
+                    } else {
+                        phiInit = lastLoop.loopEntryAnyLocation;
+                    }
+                    PhiNode phi = lastLoop.loopBegin.graph().add(new PhiNode(PhiType.Memory, lastLoop.loopBegin));
+                    phi.addInput(phiInit);
+                    lastLoop.state.lastMemorySnapshot.put(locationIdentity, phi);
+                    lastLoop.loopPhiLocations.put(phi, locationIdentity);
+                    tryFinishLoopPhis(lastLoop.state, lastLoop.loopBegin);
+                    lastLocationAccess = phi;
+                }
+                state.lastMemorySnapshot.put(locationIdentity, lastLocationAccess);
+            }
+        }
+        return lastLocationAccess;
+    }
+
+    private static void processLoopExit(LoopExitNode exit, MemoryMap state) {
+        for (Map.Entry<Object, ValueNode> entry : state.lastMemorySnapshot.entrySet()) {
+            entry.setValue(exit.graph().unique(new ValueProxyNode(entry.getValue(), exit, PhiType.Memory)));
+        }
+        if (!state.loops.isEmpty()) {
+            state.loops.pop();
+        }
+    }
+
+    private void tryFinishLoopPhis(MemoryMap loopMemory, LoopBeginNode loopBegin) {
+        List<MemoryMap> loopEndStates = loopEndStatesMap.get(loopBegin);
+        if (loopEndStates == null) {
+            return;
+        }
+        LoopState loopState = loopMemory.loops.get(0);
+        int i = 0;
+        while (loopState.loopBegin != loopBegin) {
+            loopState = loopMemory.loops.get(++i);
+        }
+        for (PhiNode phi : loopBegin.phis()) {
+            if (phi.type() == PhiType.Memory && phi.valueCount() == 1) {
+                Object location = loopState.loopPhiLocations.get(phi);
+                assert location != null : "unknown location for " + phi;
+                for (MemoryMap endState : loopEndStates) {
+                    ValueNode otherNode = endState.lastMemorySnapshot.get(location);
+                    if (otherNode == null) {
+                        otherNode = endState.lastMemorySnapshot.get(LocationNode.ANY_LOCATION);
+                    }
+                    phi.addInput(otherNode);
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/GlobalValueNumberingPhase.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.phases.phases;
+
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+
+public class GlobalValueNumberingPhase extends Phase {
+
+    public static final DebugMetric metricGlobalValueNumberingHits = Debug.metric("GlobalValueNumberingHits");
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        NodeBitMap visited = graph.createNodeBitMap();
+        for (Node n : graph.getNodes()) {
+            apply(n, visited, graph);
+        }
+    }
+
+    private void apply(Node n, NodeBitMap visited, StructuredGraph compilerGraph) {
+        if (!visited.isMarked(n)) {
+            visited.mark(n);
+            for (Node input : n.inputs()) {
+                apply(input, visited, compilerGraph);
+            }
+            if (n.getNodeClass().valueNumberable()) {
+                Node newNode = compilerGraph.findDuplicate(n);
+                if (newNode != null) {
+                    assert !(n instanceof FixedNode || newNode instanceof FixedNode);
+                    n.replaceAtUsages(newNode);
+                    n.safeDelete();
+                    metricGlobalValueNumberingHits.increment();
+                    Debug.log("GVN applied and new node is %1s", newNode);
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/IdentifyBoxingPhase.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.phases.phases;
+
+import java.lang.reflect.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.java.*;
+
+public class IdentifyBoxingPhase extends Phase {
+
+    private final BoxingMethodPool pool;
+
+    public IdentifyBoxingPhase(BoxingMethodPool pool) {
+        this.pool = pool;
+    }
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        for (Invoke invoke : graph.getInvokes()) {
+            tryIntrinsify(invoke);
+        }
+    }
+
+    public void tryIntrinsify(Invoke invoke) {
+        if (!(invoke.callTarget() instanceof MethodCallTargetNode)) {
+            return;
+        }
+        MethodCallTargetNode callTarget = invoke.methodCallTarget();
+        ResolvedJavaMethod targetMethod = callTarget.targetMethod();
+        if (pool.isSpecialMethod(targetMethod)) {
+            assert callTarget.arguments().size() == 1 : "boxing/unboxing method must have exactly one argument";
+            Kind returnKind = callTarget.returnKind();
+            ValueNode sourceValue = callTarget.arguments().get(0);
+
+            // Check whether this is a boxing or an unboxing.
+            Node newNode = null;
+            if (returnKind == Kind.Object) {
+                // We have a boxing method here.
+                assert Modifier.isStatic(targetMethod.accessFlags()) : "boxing method must be static";
+                Kind sourceKind = targetMethod.signature().argumentKindAt(0);
+                newNode = invoke.graph().add(new BoxNode(sourceValue, targetMethod.holder(), sourceKind, invoke.bci()));
+            } else {
+                // We have an unboxing method here.
+                assert !Modifier.isStatic(targetMethod.accessFlags()) : "unboxing method must be an instance method";
+                newNode = invoke.graph().add(new UnboxNode(returnKind, sourceValue));
+            }
+
+            // Intrinsify the invoke to the special node.
+            invoke.intrinsify(newNode);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/InliningPhase.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,420 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.phases.phases;
+
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.debug.internal.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.phases.PhasePlan.*;
+import com.oracle.graal.phases.util.*;
+import com.oracle.graal.phases.util.InliningUtil.*;
+
+
+public class InliningPhase extends Phase implements InliningCallback {
+    /*
+     * - Detect method which only call another method with some parameters set to constants: void foo(a) -> void foo(a, b) -> void foo(a, b, c) ...
+     *   These should not be taken into account when determining inlining depth.
+     * - honor the result of overrideInliningDecision(0, caller, invoke.bci, method, true);
+     */
+
+    private final TargetDescription target;
+    private final GraalCodeCacheProvider runtime;
+
+    private final Collection<? extends Invoke> hints;
+
+    private final PriorityQueue<InlineInfo> inlineCandidates = new PriorityQueue<>();
+    private Assumptions assumptions;
+
+    private final PhasePlan plan;
+    private final GraphCache cache;
+    private final WeightComputationPolicy weightComputationPolicy;
+    private final InliningPolicy inliningPolicy;
+    private final OptimisticOptimizations optimisticOpts;
+
+    // Metrics
+    private static final DebugMetric metricInliningPerformed = Debug.metric("InliningPerformed");
+    private static final DebugMetric metricInliningConsidered = Debug.metric("InliningConsidered");
+    private static final DebugMetric metricInliningStoppedByMaxDesiredSize = Debug.metric("InliningStoppedByMaxDesiredSize");
+
+    public InliningPhase(TargetDescription target, GraalCodeCacheProvider runtime, Collection<? extends Invoke> hints, Assumptions assumptions, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts) {
+        this.target = target;
+        this.runtime = runtime;
+        this.hints = hints;
+        this.assumptions = assumptions;
+        this.cache = cache;
+        this.plan = plan;
+        this.optimisticOpts = optimisticOpts;
+        this.weightComputationPolicy = createWeightComputationPolicy();
+        this.inliningPolicy = createInliningPolicy();
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    protected void run(final StructuredGraph graph) {
+        graph.createNodeMap();
+
+        if (hints != null) {
+            scanInvokes((Iterable<? extends Node>) Util.uncheckedCast(this.hints));
+        } else {
+            scanInvokes(graph.getNodes(InvokeNode.class));
+            scanInvokes(graph.getNodes(InvokeWithExceptionNode.class));
+        }
+
+        while (!inlineCandidates.isEmpty() && graph.getNodeCount() < GraalOptions.MaximumDesiredSize) {
+            InlineInfo candidate = inlineCandidates.remove();
+            if (!candidate.invoke.node().isAlive()) {
+                continue;
+            }
+            // refresh infos
+            final InlineInfo info = InliningUtil.getInlineInfo(candidate.invoke, candidate.level, runtime, assumptions, this, optimisticOpts);
+
+            boolean inline = Debug.scope("InliningDecisions", new Callable<Boolean>() {
+                @Override
+                public Boolean call() throws Exception {
+                    return info != null && inliningPolicy.isWorthInlining(graph, info);
+                }
+            });
+
+            if (inline) {
+                int mark = graph.getMark();
+                Iterable<Node> newNodes = null;
+                try {
+                    info.inline(graph, runtime, this);
+                    Debug.dump(graph, "after %s", info);
+                    newNodes = graph.getNewNodes(mark);
+                    if (GraalOptions.OptCanonicalizer) {
+                        new CanonicalizerPhase(target, runtime, assumptions, mark, null).apply(graph);
+                    }
+//                    if (GraalOptions.Intrinsify) {
+//                        new IntrinsificationPhase(runtime).apply(graph);
+//                    }
+                    metricInliningPerformed.increment();
+                } catch (BailoutException bailout) {
+                    // TODO determine if we should really bail out of the whole compilation.
+                    throw bailout;
+                } catch (AssertionError e) {
+                    throw new GraalInternalError(e).addContext(info.toString());
+                } catch (RuntimeException e) {
+                    throw new GraalInternalError(e).addContext(info.toString());
+                } catch (GraalInternalError e) {
+                    throw e.addContext(info.toString());
+                }
+
+                if (newNodes != null && info.level < GraalOptions.MaximumInlineLevel) {
+                    scanInvokes(newNodes);
+                }
+            }
+        }
+
+        if (GraalOptions.Debug && graph.getNodeCount() >= GraalOptions.MaximumDesiredSize) {
+            Debug.scope("InliningDecisions", new Runnable() {
+                public void run() {
+                    for (InlineInfo info : inlineCandidates) {
+                        Debug.log("not inlining %s because inlining cut off by MaximumDesiredSize", InliningUtil.methodName(info));
+                    }
+                }
+            });
+
+            metricInliningStoppedByMaxDesiredSize.increment();
+        }
+    }
+
+    private void scanInvokes(final Iterable<? extends Node> nodes) {
+        Debug.scope("InliningDecisions", new Runnable() {
+            public void run() {
+                for (Node node : nodes) {
+                    if (node != null) {
+                        if (node instanceof Invoke) {
+                            Invoke invoke = (Invoke) node;
+                            scanInvoke(invoke);
+                        }
+                        for (Node usage : node.usages().filterInterface(Invoke.class).snapshot()) {
+                            scanInvoke((Invoke) usage);
+                        }
+                    }
+                }
+            }
+        });
+    }
+
+    private void scanInvoke(Invoke invoke) {
+        InlineInfo info = InliningUtil.getInlineInfo(invoke, computeInliningLevel(invoke), runtime, assumptions, this, optimisticOpts);
+        if (info != null) {
+            metricInliningConsidered.increment();
+            inlineCandidates.add(info);
+        }
+    }
+
+    public static final Map<JavaMethod, Integer> parsedMethods = new HashMap<>();
+
+
+
+    private static final DebugMetric metricInliningRuns = Debug.metric("Runs");
+
+    @Override
+    public StructuredGraph buildGraph(final ResolvedJavaMethod method) {
+        metricInliningRuns.increment();
+        if (GraalOptions.CacheGraphs && cache != null) {
+            StructuredGraph cachedGraph = cache.get(method);
+            if (cachedGraph != null) {
+                return cachedGraph;
+            }
+        }
+        StructuredGraph newGraph = new StructuredGraph(method);
+        if (plan != null) {
+            plan.runPhases(PhasePosition.AFTER_PARSING, newGraph);
+        }
+        assert newGraph.start().next() != null : "graph needs to be populated during PhasePosition.AFTER_PARSING";
+
+        if (GraalOptions.ProbabilityAnalysis) {
+            new DeadCodeEliminationPhase().apply(newGraph);
+            new ComputeProbabilityPhase().apply(newGraph);
+        }
+        if (GraalOptions.OptCanonicalizer) {
+            new CanonicalizerPhase(target, runtime, assumptions).apply(newGraph);
+        }
+        if (GraalOptions.Intrinsify) {
+            new IntrinsificationPhase(runtime).apply(newGraph);
+        }
+        if (GraalOptions.CullFrameStates) {
+            new CullFrameStatesPhase().apply(newGraph);
+        }
+        if (GraalOptions.CacheGraphs && cache != null) {
+            cache.put(newGraph);
+        }
+        return newGraph;
+    }
+
+    @Override
+    public double inliningWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke) {
+        boolean preferred = hints != null && hints.contains(invoke);
+        return weightComputationPolicy.computeWeight(caller, method, invoke, preferred);
+    }
+
+    public static int graphComplexity(StructuredGraph graph) {
+        int result = 0;
+        for (Node node : graph.getNodes()) {
+            if (node instanceof ConstantNode || node instanceof LocalNode || node instanceof BeginNode || node instanceof ReturnNode || node instanceof UnwindNode) {
+                result += 0;
+            } else if (node instanceof PhiNode) {
+                result += 5;
+            } else if (node instanceof MergeNode || node instanceof Invoke || node instanceof LoopEndNode || node instanceof EndNode) {
+                result += 0;
+            } else if (node instanceof ControlSplitNode) {
+                result += ((ControlSplitNode) node).blockSuccessorCount();
+            } else {
+                result += 1;
+            }
+        }
+        return Math.max(1, result);
+    }
+
+
+    @Override
+    public void recordConcreteMethodAssumption(ResolvedJavaMethod method, ResolvedJavaType context, ResolvedJavaMethod impl) {
+        assumptions.recordConcreteMethod(method, context, impl);
+    }
+
+    @Override
+    public void recordMethodContentsAssumption(ResolvedJavaMethod method) {
+        if (assumptions != null) {
+            assumptions.recordMethodContents(method);
+        }
+    }
+
+    private static int computeInliningLevel(Invoke invoke) {
+        int count = -1;
+        FrameState curState = invoke.stateAfter();
+        while (curState != null) {
+            count++;
+            curState = curState.outerFrameState();
+        }
+        return count;
+    }
+
+    private static InliningPolicy createInliningPolicy() {
+        switch(GraalOptions.InliningPolicy) {
+            case 0: return new WeightBasedInliningPolicy();
+            case 1: return new C1StaticSizeBasedInliningPolicy();
+            case 2: return new MinimumCodeSizeBasedInliningPolicy();
+            case 3: return new DynamicSizeBasedInliningPolicy();
+            case 4: return new GreedySizeBasedInliningPolicy();
+            default:
+                GraalInternalError.shouldNotReachHere();
+                return null;
+        }
+    }
+
+    private static WeightComputationPolicy createWeightComputationPolicy() {
+        switch(GraalOptions.WeightComputationPolicy) {
+            case 0: throw new GraalInternalError("removed because of invokation counter changes");
+            case 1: return new BytecodeSizeBasedWeightComputationPolicy();
+            case 2: return new ComplexityBasedWeightComputationPolicy();
+            default:
+                GraalInternalError.shouldNotReachHere();
+                return null;
+        }
+    }
+
+    private interface InliningPolicy {
+        boolean isWorthInlining(StructuredGraph callerGraph, InlineInfo info);
+    }
+
+    private static class WeightBasedInliningPolicy implements InliningPolicy {
+        @Override
+        public boolean isWorthInlining(StructuredGraph callerGraph, InlineInfo info) {
+            if (!checkCompiledCodeSize(info)) {
+                return false;
+            }
+
+            double penalty = Math.pow(GraalOptions.InliningSizePenaltyExp, callerGraph.getNodeCount() / (double) GraalOptions.MaximumDesiredSize) / GraalOptions.InliningSizePenaltyExp;
+            if (info.weight > GraalOptions.MaximumInlineWeight / (1 + penalty * GraalOptions.InliningSizePenalty)) {
+                Debug.log("not inlining %s (cut off by weight %e)", InliningUtil.methodName(info), info.weight);
+                return false;
+            }
+
+            Debug.log("inlining %s (weight %f): %s", InliningUtil.methodName(info), info.weight);
+            return true;
+        }
+    }
+
+    private static class C1StaticSizeBasedInliningPolicy implements InliningPolicy {
+        @Override
+        public boolean isWorthInlining(StructuredGraph callerGraph, InlineInfo info) {
+            double maxSize = Math.max(GraalOptions.MaximumTrivialSize, Math.pow(GraalOptions.NestedInliningSizeRatio, info.level) * GraalOptions.MaximumInlineSize);
+            return decideSizeBasedInlining(info, maxSize);
+        }
+    }
+
+    private static class MinimumCodeSizeBasedInliningPolicy implements InliningPolicy {
+        @Override
+        public boolean isWorthInlining(StructuredGraph callerGraph, InlineInfo info) {
+            assert GraalOptions.ProbabilityAnalysis;
+            if (!checkCompiledCodeSize(info)) {
+                return false;
+            }
+
+            double inlineWeight = Math.min(GraalOptions.ProbabilityCapForInlining, info.invoke.probability());
+            double maxSize = Math.pow(GraalOptions.NestedInliningSizeRatio, info.level) * GraalOptions.MaximumInlineSize * inlineWeight;
+            maxSize = Math.max(GraalOptions.MaximumTrivialSize, maxSize);
+
+            return decideSizeBasedInlining(info, maxSize);
+        }
+    }
+
+    private static class DynamicSizeBasedInliningPolicy implements InliningPolicy {
+        @Override
+        public boolean isWorthInlining(StructuredGraph callerGraph, InlineInfo info) {
+            assert GraalOptions.ProbabilityAnalysis;
+            if (!checkCompiledCodeSize(info)) {
+                return false;
+            }
+
+            double inlineBoost = Math.min(GraalOptions.ProbabilityCapForInlining, info.invoke.probability()) + Math.log10(Math.max(1, info.invoke.probability() - GraalOptions.ProbabilityCapForInlining + 1));
+            double maxSize = Math.pow(GraalOptions.NestedInliningSizeRatio, info.level) * GraalOptions.MaximumInlineSize;
+            maxSize = maxSize + maxSize * inlineBoost;
+            maxSize = Math.min(GraalOptions.MaximumGreedyInlineSize, Math.max(GraalOptions.MaximumTrivialSize, maxSize));
+
+            return decideSizeBasedInlining(info, maxSize);
+        }
+    }
+
+    private static class GreedySizeBasedInliningPolicy implements InliningPolicy {
+        @Override
+        public boolean isWorthInlining(StructuredGraph callerGraph, InlineInfo info) {
+            assert GraalOptions.ProbabilityAnalysis;
+            if (!checkCompiledCodeSize(info)) {
+                return false;
+            }
+
+            double maxSize = GraalOptions.MaximumGreedyInlineSize;
+            if (GraalOptions.InliningBonusPerTransferredValue != 0) {
+                Signature signature = info.invoke.methodCallTarget().targetMethod().signature();
+                int transferredValues = signature.argumentCount(!Modifier.isStatic(info.invoke.methodCallTarget().targetMethod().accessFlags()));
+                if (signature.returnKind() != Kind.Void) {
+                    transferredValues++;
+                }
+                maxSize += transferredValues * GraalOptions.InliningBonusPerTransferredValue;
+            }
+
+            double inlineRatio = Math.min(GraalOptions.ProbabilityCapForInlining, info.invoke.probability());
+            maxSize = Math.pow(GraalOptions.NestedInliningSizeRatio, info.level) * maxSize * inlineRatio;
+            maxSize = Math.max(maxSize, GraalOptions.MaximumTrivialSize);
+
+            return decideSizeBasedInlining(info, maxSize);
+        }
+    }
+
+    private static boolean decideSizeBasedInlining(InlineInfo info, double maxSize) {
+        boolean success = info.weight <= maxSize;
+        if (DebugScope.getInstance().isLogEnabled()) {
+            String formatterString = success ? "inlining %s (size %f <= %f)" : "not inlining %s (too large %f > %f)";
+            Debug.log(formatterString, InliningUtil.methodName(info), info.weight, maxSize);
+        }
+        return success;
+    }
+
+    private static boolean checkCompiledCodeSize(InlineInfo info) {
+        if (GraalOptions.SmallCompiledCodeSize >= 0 && info.compiledCodeSize() > GraalOptions.SmallCompiledCodeSize) {
+            Debug.log("not inlining %s (CompiledCodeSize %d > %d)", InliningUtil.methodName(info), info.compiledCodeSize(), GraalOptions.SmallCompiledCodeSize);
+            return false;
+        }
+        return true;
+    }
+
+
+    private interface WeightComputationPolicy {
+        double computeWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke, boolean preferredInvoke);
+    }
+
+    private static class BytecodeSizeBasedWeightComputationPolicy implements WeightComputationPolicy {
+        @Override
+        public double computeWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke, boolean preferredInvoke) {
+            double codeSize = method.codeSize();
+            if (preferredInvoke) {
+                codeSize = codeSize / GraalOptions.BoostInliningForEscapeAnalysis;
+            }
+            return codeSize;
+        }
+    }
+
+    private static class ComplexityBasedWeightComputationPolicy implements WeightComputationPolicy {
+        @Override
+        public double computeWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke, boolean preferredInvoke) {
+            double complexity = method.compilationComplexity();
+            if (preferredInvoke) {
+                complexity = complexity / GraalOptions.BoostInliningForEscapeAnalysis;
+            }
+            return complexity;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/InsertStateAfterPlaceholderPhase.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 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 com.oracle.graal.phases.phases;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+public class InsertStateAfterPlaceholderPhase extends Phase {
+
+    private static class PlaceholderNode extends AbstractStateSplit implements StateSplit, Node.IterableNodeType, LIRLowerable, Canonicalizable {
+        public PlaceholderNode() {
+            super(StampFactory.forVoid());
+        }
+
+        @Override
+        public void generate(LIRGeneratorTool gen) {
+            // nothing to do
+        }
+
+        @Override
+        public boolean hasSideEffect(CodeCacheProvider runtime) {
+            return false;
+        }
+
+        @Override
+        public ValueNode canonical(CanonicalizerTool tool) {
+            if (stateAfter() == null) {
+                return null;
+            }
+            return this;
+        }
+    }
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        for (ReturnNode ret : graph.getNodes(ReturnNode.class)) {
+            PlaceholderNode p = graph.add(new PlaceholderNode());
+            p.setStateAfter(graph.add(new FrameState(FrameState.AFTER_BCI)));
+            graph.addBeforeFixed(ret, p);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/IntrinsificationPhase.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.phases.phases;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.phases.util.*;
+
+public class IntrinsificationPhase extends Phase {
+
+    private final GraalCodeCacheProvider runtime;
+
+    public IntrinsificationPhase(GraalCodeCacheProvider runtime) {
+        this.runtime = runtime;
+    }
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        for (InvokeNode invoke : graph.getNodes(InvokeNode.class)) {
+            tryIntrinsify(invoke, runtime);
+        }
+        for (InvokeWithExceptionNode invoke : graph.getNodes(InvokeWithExceptionNode.class)) {
+            tryIntrinsify(invoke, runtime);
+        }
+    }
+
+    public static boolean canIntrinsify(Invoke invoke, ResolvedJavaMethod target, GraalCodeCacheProvider runtime) {
+        return getIntrinsicGraph(invoke, target, runtime) != null;
+    }
+
+    private static void tryIntrinsify(Invoke invoke, GraalCodeCacheProvider runtime) {
+        if (invoke.callTarget() instanceof MethodCallTargetNode && invoke.methodCallTarget().targetMethod() != null) {
+            tryIntrinsify(invoke, invoke.methodCallTarget().targetMethod(), runtime);
+        }
+    }
+
+    private static void tryIntrinsify(Invoke invoke, ResolvedJavaMethod target, GraalCodeCacheProvider runtime) {
+        StructuredGraph intrinsicGraph = getIntrinsicGraph(invoke, target, runtime);
+        if (intrinsicGraph != null) {
+            Debug.log(" > Intrinsify %s", target);
+            InliningUtil.inline(invoke, intrinsicGraph, true);
+        }
+    }
+
+    private static StructuredGraph getIntrinsicGraph(Invoke invoke, ResolvedJavaMethod target, GraalCodeCacheProvider runtime) {
+        StructuredGraph intrinsicGraph = (StructuredGraph) target.compilerStorage().get(Graph.class);
+        if (intrinsicGraph == null) {
+            // TODO remove once all intrinsics are available via compilerStorage
+            intrinsicGraph = runtime.intrinsicGraph(invoke.stateAfter().method(), invoke.bci(), target, invoke.callTarget().arguments());
+        }
+        return intrinsicGraph;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/IterativeCheckCastEliminationPhase.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 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 com.oracle.graal.phases.phases;
+
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.Graph.InputChangedListener;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+
+
+public class IterativeCheckCastEliminationPhase extends Phase {
+    private final TargetDescription target;
+    private final MetaAccessProvider runtime;
+    private final Assumptions assumptions;
+
+    public IterativeCheckCastEliminationPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions) {
+        this.target = target;
+        this.runtime = runtime;
+        this.assumptions = assumptions;
+    }
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        Set<Node> canonicalizationRoots = new HashSet<>();
+        CheckCastEliminationPhase eliminate = new CheckCastEliminationPhase();
+        Listener listener = new Listener(canonicalizationRoots);
+        while (true) {
+            graph.trackInputChange(listener);
+            eliminate.apply(graph);
+            graph.stopTrackingInputChange();
+            if (canonicalizationRoots.isEmpty()) {
+                break;
+            }
+            new CanonicalizerPhase(target, runtime, assumptions, canonicalizationRoots, null).apply(graph);
+            canonicalizationRoots.clear();
+        }
+    }
+
+    private static class Listener implements InputChangedListener {
+        private final Set<Node> canonicalizationRoots;
+        public Listener(Set<Node> canonicalizationRoots) {
+            this.canonicalizationRoots = canonicalizationRoots;
+        }
+        @Override
+        public void inputChanged(Node node) {
+            canonicalizationRoots.add(node);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/LoopSafepointInsertionPhase.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.phases.phases;
+
+import com.oracle.graal.graph.iterators.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.util.*;
+
+/**
+ * Adds safepoints to loops.
+ */
+public class LoopSafepointInsertionPhase extends Phase {
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        nextLoop:
+        for (LoopEndNode loopEnd : graph.getNodes(LoopEndNode.class)) {
+            if (!loopEnd.canSafepoint()) {
+                continue;
+            }
+            if (GraalOptions.OptSafepointElimination) {
+                // We 'eliminate' safepoints by simply never placing them into loops that have at least one call
+                NodeIterable<FixedNode> it = NodeIterators.dominators(loopEnd).until(loopEnd.loopBegin());
+                for (FixedNode n : it) {
+                    if (n instanceof Invoke) {
+                        continue nextLoop;
+                    }
+                }
+            }
+            SafepointNode safepoint = graph.add(new SafepointNode());
+            graph.addBeforeFixed(loopEnd, safepoint);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/LoweringPhase.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.phases.phases;
+
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.iterators.*;
+import com.oracle.graal.lir.cfg.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.schedule.*;
+
+/**
+ * Processes all {@link Lowerable} nodes to do their lowering.
+ */
+public class LoweringPhase extends Phase {
+
+    final class LoweringToolImpl implements LoweringTool {
+
+        final FixedNode guardAnchor;
+        final NodeBitMap activeGuards;
+        FixedWithNextNode lastFixedNode;
+
+        public LoweringToolImpl(FixedNode guardAnchor, NodeBitMap activeGuards) {
+            this.guardAnchor = guardAnchor;
+            this.activeGuards = activeGuards;
+        }
+
+        @Override
+        public GraalCodeCacheProvider getRuntime() {
+            return runtime;
+        }
+
+        @Override
+        public ValueNode createNullCheckGuard(ValueNode object, long leafGraphId) {
+            return createGuard(object.graph().unique(new IsNullNode(object)), DeoptimizationReason.NullCheckException, DeoptimizationAction.InvalidateReprofile, true, leafGraphId);
+        }
+
+        @Override
+        public ValueNode createGuard(BooleanNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, long leafGraphId) {
+            return createGuard(condition, deoptReason, action, false, leafGraphId);
+        }
+
+        @Override
+        public Assumptions assumptions() {
+            return assumptions;
+        }
+
+        @Override
+        public ValueNode createGuard(BooleanNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated, long leafGraphId) {
+            if (GraalOptions.OptEliminateGuards) {
+                for (Node usage : condition.usages()) {
+                    if (!activeGuards.isNew(usage) && activeGuards.isMarked(usage)) {
+                        return (ValueNode) usage;
+                    }
+                }
+            }
+            GuardNode newGuard = guardAnchor.graph().unique(new GuardNode(condition, guardAnchor, deoptReason, action, negated, leafGraphId));
+            if (GraalOptions.OptEliminateGuards) {
+                activeGuards.grow();
+                activeGuards.mark(newGuard);
+            }
+            return newGuard;
+        }
+
+        public FixedWithNextNode lastFixedNode() {
+            return lastFixedNode;
+        }
+    }
+
+    private final GraalCodeCacheProvider runtime;
+    private final Assumptions assumptions;
+
+    public LoweringPhase(GraalCodeCacheProvider runtime, Assumptions assumptions) {
+        this.runtime = runtime;
+        this.assumptions = assumptions;
+    }
+
+    private static boolean containsLowerable(NodeIterable<Node> nodes) {
+        for (Node n : nodes) {
+            if (n instanceof Lowerable) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    protected void run(final StructuredGraph graph) {
+        int  i = 0;
+        NodeBitMap processed = graph.createNodeBitMap();
+        while (true) {
+            int mark = graph.getMark();
+            final SchedulePhase schedule = new SchedulePhase();
+            schedule.apply(graph, false);
+
+            processBlock(schedule.getCFG().getStartBlock(), graph.createNodeBitMap(), null, schedule, processed);
+            Debug.dump(graph, "Lowering iteration %d", i++);
+            new CanonicalizerPhase(null, runtime, assumptions, mark, null).apply(graph);
+
+            if (!containsLowerable(graph.getNewNodes(mark))) {
+                // No new lowerable nodes - done!
+                break;
+            }
+            assert graph.verify();
+            processed.grow();
+        }
+    }
+
+    private void processBlock(Block block, NodeBitMap activeGuards, FixedNode parentAnchor, SchedulePhase schedule, NodeBitMap processed) {
+
+        FixedNode anchor = parentAnchor;
+        if (anchor == null) {
+            anchor = block.getBeginNode();
+        }
+        process(block, activeGuards, anchor, schedule, processed);
+
+        // Process always reached block first.
+        Block alwaysReachedBlock = block.getPostdominator();
+        if (alwaysReachedBlock != null && alwaysReachedBlock.getDominator() == block) {
+            processBlock(alwaysReachedBlock, activeGuards, anchor, schedule, processed);
+        }
+
+        // Now go for the other dominators.
+        for (Block dominated : block.getDominated()) {
+            if (dominated != alwaysReachedBlock) {
+                assert dominated.getDominator() == block;
+                processBlock(dominated, activeGuards, null, schedule, processed);
+            }
+        }
+
+        if (parentAnchor == null && GraalOptions.OptEliminateGuards) {
+            for (GuardNode guard : anchor.usages().filter(GuardNode.class)) {
+                activeGuards.clear(guard);
+            }
+        }
+    }
+
+    private void process(final Block b, final NodeBitMap activeGuards, final FixedNode anchor, SchedulePhase schedule, NodeBitMap processed) {
+
+        final LoweringToolImpl loweringTool = new LoweringToolImpl(anchor, activeGuards);
+
+        // Lower the instructions of this block.
+        List<ScheduledNode> nodes = schedule.nodesFor(b);
+
+        for (Node node : nodes) {
+            FixedNode lastFixedNext = null;
+            if (node instanceof FixedWithNextNode) {
+                FixedWithNextNode fixed = (FixedWithNextNode) node;
+                lastFixedNext = fixed.next();
+                loweringTool.lastFixedNode = fixed;
+            }
+
+            if (node.isAlive() && !processed.isMarked(node)) {
+                processed.mark(node);
+                if (node instanceof Lowerable) {
+                    ((Lowerable) node).lower(loweringTool);
+                }
+            }
+
+            if (loweringTool.lastFixedNode == node && !node.isAlive()) {
+                if (lastFixedNext == null) {
+                    loweringTool.lastFixedNode = null;
+                } else {
+                    Node prev = lastFixedNext.predecessor();
+                    if (prev != node && prev instanceof FixedWithNextNode) {
+                        loweringTool.lastFixedNode = (FixedWithNextNode) prev;
+                    } else if (lastFixedNext instanceof FixedWithNextNode) {
+                        loweringTool.lastFixedNode = (FixedWithNextNode) lastFixedNext;
+                    } else {
+                        loweringTool.lastFixedNode = null;
+                    }
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/Phase.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.phases.phases;
+
+import com.oracle.graal.debug.*;
+import com.oracle.graal.nodes.*;
+
+public abstract class Phase {
+
+    private String name;
+    private static final DebugMetric metricPhaseRuns = Debug.metric("Runs");
+    protected static final DebugMetric METRIC_PROCESSED_NODES = Debug.metric("ProcessedNodes");
+
+    protected Phase() {
+        this.name = this.getClass().getSimpleName();
+        if (name.endsWith("Phase")) {
+            name = name.substring(0, name.length() - "Phase".length());
+        }
+    }
+
+    protected Phase(String name) {
+        this.name = name;
+    }
+
+    protected String getDetailedName() {
+        return getName();
+    }
+
+    public final void apply(final StructuredGraph graph) {
+        apply(graph, true);
+    }
+
+    public final void apply(final StructuredGraph graph, final boolean dumpGraph) {
+        Debug.scope(name, this, new Runnable() {
+            public void run() {
+                Phase.this.run(graph);
+                metricPhaseRuns.increment();
+                if (dumpGraph) {
+                    Debug.dump(graph, "After phase %s", name);
+                }
+                assert graph.verify();
+            }
+        });
+    }
+
+    public final String getName() {
+        return name;
+    }
+
+    protected abstract void run(StructuredGraph graph);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/PhasePlan.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.phases.phases;
+
+import java.util.*;
+
+import com.oracle.graal.nodes.*;
+
+/**
+ * Tells the compiler about additional phases that need to be executed during compilation.
+ */
+public class PhasePlan {
+    /**
+     * The compilation is split into the following sections:
+     * ========================================================================
+     * Period 1: High-level nodes. (Graph building)
+     * ========================================================================
+     * Runtime-specific lowering.
+     * ========================================================================
+     * Period 2: Mid-level nodes. (Memory dependence graph)
+     * ========================================================================
+     * Target-specific lowering, de-SSA.
+     * ========================================================================
+     * Period 3: Low-level nodes. (Register allocation, code generation)
+     * ========================================================================
+     *
+     * A compiler extension phase can chose to run at the end of periods 1-3.
+     */
+    public static enum PhasePosition {
+        AFTER_PARSING,
+        HIGH_LEVEL,
+        MID_LEVEL,
+        LOW_LEVEL
+    }
+
+    @SuppressWarnings("unchecked")
+    private final ArrayList<Phase>[] phases = new ArrayList[PhasePosition.values().length];
+    private final Set<Class<? extends Phase>> disabledPhases = new HashSet<>();
+
+    public void addPhase(PhasePosition pos, Phase phase) {
+        if (phases[pos.ordinal()] == null) {
+            phases[pos.ordinal()] = new ArrayList<>();
+        }
+        phases[pos.ordinal()].add(phase);
+    }
+
+    public void runPhases(PhasePosition pos, StructuredGraph graph) {
+        if (phases[pos.ordinal()] != null) {
+            for (Phase p : phases[pos.ordinal()]) {
+                p.apply(graph);
+            }
+        }
+    }
+
+    public void disablePhase(Class<? extends Phase> clazz) {
+        disabledPhases.add(clazz);
+    }
+
+    public boolean isPhaseDisabled(Class<? extends Phase> clazz) {
+        return disabledPhases.contains(clazz);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/PhiStampPhase.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.phases.phases;
+
+import com.oracle.graal.nodes.*;
+
+public class PhiStampPhase extends Phase {
+    @Override
+    protected void run(StructuredGraph graph) {
+        // Infer phis stopping at loop phis.
+        for (PhiNode phi : graph.getNodes(PhiNode.class)) {
+            inferPhi(phi);
+        }
+
+        // Start iterative inference for loop phis.
+        if (graph.hasLoops()) {
+            for (PhiNode phi : graph.getNodes(PhiNode.class)) {
+                if (phi.isLoopPhi()) {
+                    iterativeInferPhi(phi);
+                }
+            }
+        }
+    }
+
+    private void iterativeInferPhi(PhiNode phi) {
+        if (phi.inferPhiStamp()) {
+            for (PhiNode phiUsage : phi.usages().filter(PhiNode.class)) {
+                iterativeInferPhi(phiUsage);
+            }
+        }
+    }
+
+    private void inferPhi(PhiNode phi) {
+        for (PhiNode phiInput : phi.values().filter(PhiNode.class)) {
+            if (!phiInput.isLoopPhi()) {
+                inferPhi(phiInput);
+            }
+        }
+        phi.inferPhiStamp();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/ReadEliminationPhase.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.phases.phases;
+
+import java.util.*;
+
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.PhiNode.PhiType;
+import com.oracle.graal.nodes.extended.*;
+
+public class ReadEliminationPhase extends Phase {
+    private Queue<PhiNode> newPhis;
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        newPhis = new LinkedList<>();
+        for (FloatingReadNode n : graph.getNodes(FloatingReadNode.class)) {
+            if (isReadEliminable(n)) {
+                NodeMap<ValueNode> nodeMap = n.graph().createNodeMap();
+                ValueNode value = getValue(n, n.lastLocationAccess(), nodeMap);
+                Debug.log("Eliminated memory read %1.1s and replaced with node %s", n, value);
+                graph.replaceFloating(n, value);
+            }
+        }
+    }
+
+    private boolean isReadEliminable(FloatingReadNode n) {
+        return isWrites(n, n.lastLocationAccess(), n.graph().createNodeBitMap());
+    }
+
+    private boolean isWrites(FloatingReadNode n, Node lastLocationAccess, NodeBitMap visited) {
+        if (lastLocationAccess == null) {
+            return false;
+        }
+        if (visited.isMarked(lastLocationAccess)) {
+            return true; // dataflow loops must come from Phis assume them ok until proven wrong
+        }
+        if (lastLocationAccess instanceof ValueProxyNode) {
+            return isWrites(n, ((ValueProxyNode) lastLocationAccess).value(), visited);
+        }
+        if (lastLocationAccess instanceof WriteNode) {
+            WriteNode other = (WriteNode) lastLocationAccess;
+            return other.object() == n.object() && other.location() == n.location();
+        }
+        if (lastLocationAccess instanceof PhiNode) {
+            visited.mark(lastLocationAccess);
+            for (ValueNode value : ((PhiNode) lastLocationAccess).values()) {
+                if (!isWrites(n, value, visited)) {
+                    return false;
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    private ValueNode getValue(FloatingReadNode n, Node lastLocationAccess, NodeMap<ValueNode> nodeMap) {
+        ValueNode exisiting = nodeMap.get(lastLocationAccess);
+        if (exisiting != null) {
+            return exisiting;
+        }
+        if (lastLocationAccess instanceof ValueProxyNode) {
+            ValueProxyNode proxy = (ValueProxyNode) lastLocationAccess;
+            ValueNode value = getValue(n, proxy.value(), nodeMap);
+            return lastLocationAccess.graph().add(new ValueProxyNode(value, proxy.proxyPoint(), PhiType.Value));
+        }
+        if (lastLocationAccess instanceof WriteNode) {
+            return ((WriteNode) lastLocationAccess).value();
+        }
+        if (lastLocationAccess instanceof PhiNode) {
+            PhiNode phi = (PhiNode) lastLocationAccess;
+            PhiNode newPhi = phi.graph().add(new PhiNode(n.kind(), phi.merge()));
+            nodeMap.set(lastLocationAccess, newPhi);
+            for (ValueNode value : phi.values()) {
+                newPhi.addInput(getValue(n, value, nodeMap));
+            }
+            newPhis.add(newPhi);
+            return newPhi;
+        }
+        throw GraalInternalError.shouldNotReachHere();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/RemoveValueProxyPhase.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 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 com.oracle.graal.phases.phases;
+
+import com.oracle.graal.nodes.*;
+
+public class RemoveValueProxyPhase extends Phase {
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        for (ValueProxyNode vpn : graph.getNodes(ValueProxyNode.class)) {
+            graph.replaceFloating(vpn, vpn.value());
+        }
+        for (LoopExitNode exit : graph.getNodes(LoopExitNode.class)) {
+            FrameState stateAfter = exit.stateAfter();
+            if (stateAfter != null) {
+                exit.setStateAfter(null);
+                if (stateAfter.usages().count() == 0) {
+                    stateAfter.safeDelete();
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/phases/TailDuplicationPhase.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,551 @@
+/*
+ * Copyright (c) 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 com.oracle.graal.phases.phases;
+
+import java.util.*;
+
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.Graph.DuplicationReplacement;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.VirtualState.NodeClosure;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.phases.*;
+
+/**
+ * This class is a phase that looks for opportunities for tail duplication. The static method
+ * {@link #tailDuplicate(MergeNode, TailDuplicationDecision, List)} can also be used to drive tail duplication from
+ * other places, e.g., inlining.
+ */
+public class TailDuplicationPhase extends Phase {
+
+    /*
+     * Various metrics on the circumstances in which tail duplication was/wasn't performed.
+     */
+    private static final DebugMetric metricDuplicationMonitors = Debug.metric("DuplicationMonitors");
+    private static final DebugMetric metricDuplicationEnd = Debug.metric("DuplicationEnd");
+    private static final DebugMetric metricDuplicationEndPerformed = Debug.metric("DuplicationEndPerformed");
+    private static final DebugMetric metricDuplicationOther = Debug.metric("DuplicationOther");
+    private static final DebugMetric metricDuplicationOtherPerformed = Debug.metric("DuplicationOtherPerformed");
+
+    /**
+     * This interface is used by tail duplication to let clients decide if tail duplication should be performed.
+     */
+    public interface TailDuplicationDecision {
+
+        /**
+         * Queries if tail duplication should be performed at the given merge. If this method returns true then the tail
+         * duplication will be performed, because all other checks have happened before.
+         *
+         * @param merge The merge at which tail duplication can be performed.
+         * @param fixedNodeCount The size of the set of fixed nodes that forms the base for the duplicated set of nodes.
+         * @return true if the tail duplication should be performed, false otherwise.
+         */
+        boolean doTransform(MergeNode merge, int fixedNodeCount);
+    }
+
+    /**
+     * A tail duplication decision closure that employs the default algorithm: Check if there are any phis on the merge
+     * whose stamps improve and that have usages within the duplicated set of fixed nodes.
+     */
+    public static final TailDuplicationDecision DEFAULT_DECISION = new TailDuplicationDecision() {
+
+        public boolean doTransform(MergeNode merge, int fixedNodeCount) {
+            if (fixedNodeCount < GraalOptions.TailDuplicationTrivialSize) {
+                return true;
+            }
+            HashSet<PhiNode> improvements = new HashSet<>();
+            for (PhiNode phi : merge.phis()) {
+                Stamp phiStamp = phi.stamp();
+                for (ValueNode input : phi.values()) {
+                    if (!input.stamp().equals(phiStamp)) {
+                        improvements.add(phi);
+                        break;
+                    }
+                }
+            }
+            if (improvements.isEmpty()) {
+                return false;
+            }
+            FixedNode current = merge;
+            int opportunities = 0;
+            while (current instanceof FixedWithNextNode) {
+                current = ((FixedWithNextNode) current).next();
+                for (PhiNode phi : improvements) {
+                    for (Node input : current.inputs()) {
+                        if (input == phi) {
+                            opportunities++;
+                        }
+                        if (input.inputs().contains(phi)) {
+                            opportunities++;
+                        }
+                    }
+                }
+            }
+            return opportunities > 0;
+        }
+    };
+
+    /**
+     * A tail duplication decision closure that always returns true.
+     */
+    public static final TailDuplicationDecision TRUE_DECISION = new TailDuplicationDecision() {
+
+        @Override
+        public boolean doTransform(MergeNode merge, int fixedNodeCount) {
+            return true;
+        }
+    };
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        // A snapshot is taken here, so that new MergeNode instances aren't considered for tail duplication.
+        for (MergeNode merge : graph.getNodes(MergeNode.class).snapshot()) {
+            if (!(merge instanceof LoopBeginNode) && merge.probability() >= GraalOptions.TailDuplicationProbability) {
+                tailDuplicate(merge, DEFAULT_DECISION, null);
+            }
+        }
+    }
+
+    /**
+     * This method attempts to duplicate the tail of the given merge. The merge must not be a {@link LoopBeginNode}. If
+     * the merge is eligible for duplication (at least one fixed node in its tail, no {@link MonitorEnterNode}/
+     * {@link MonitorExitNode}, non-null {@link MergeNode#stateAfter()}) then the decision callback is used to determine
+     * whether the tail duplication should actually be performed. If replacements is non-null, then this list of
+     * {@link PiNode}s is used to replace one value per merge end.
+     *
+     * @param merge The merge whose tail should be duplicated.
+     * @param decision A callback that can make the final decision if tail duplication should occur or not.
+     * @param replacements A list of {@link PiNode}s, or null. If this list is non-null then its size needs to match the
+     *            merge's end count. Each entry can either be null or a {@link PiNode}, and is used to replace
+     *            {@link PiNode#object()} with the {@link PiNode} in the duplicated branch that corresponds to the
+     *            entry.
+     */
+    public static void tailDuplicate(MergeNode merge, TailDuplicationDecision decision, List<PiNode> replacements) {
+        assert !(merge instanceof LoopBeginNode);
+        assert replacements == null || replacements.size() == merge.forwardEndCount();
+        FixedNode fixed = merge;
+        int fixedCount = 0;
+        boolean containsMonitor = false;
+        while (fixed instanceof FixedWithNextNode) {
+            if (fixed instanceof MonitorEnterNode || fixed instanceof MonitorExitNode) {
+                containsMonitor = true;
+            }
+            fixed = ((FixedWithNextNode) fixed).next();
+            fixedCount++;
+        }
+        if (containsMonitor) {
+            // cannot currently be handled
+            // TODO (ls) re-evaluate this limitation after changes to the lock representation and the LIR generator
+            metricDuplicationMonitors.increment();
+        } else if (fixedCount > 1) {
+            if (fixed instanceof EndNode && !(((EndNode) fixed).merge() instanceof LoopBeginNode)) {
+                metricDuplicationEnd.increment();
+                if (decision.doTransform(merge, fixedCount)) {
+                    metricDuplicationEndPerformed.increment();
+                    new DuplicationOperation(merge, replacements).duplicate();
+                }
+            } else if (merge.stateAfter() != null) {
+                metricDuplicationOther.increment();
+                if (decision.doTransform(merge, fixedCount)) {
+                    metricDuplicationOtherPerformed.increment();
+                    new DuplicationOperation(merge, replacements).duplicate();
+                }
+            }
+        }
+    }
+
+    /**
+     * This class encapsulates one tail duplication operation on a specific {@link MergeNode}.
+     */
+    private static class DuplicationOperation {
+
+        private final MergeNode merge;
+        private final StructuredGraph graph;
+
+        private final HashMap<ValueNode, PhiNode> bottomPhis = new HashMap<>();
+        private final List<PiNode> replacements;
+
+        /**
+         * Initializes the tail duplication operation without actually performing any work.
+         *
+         * @param merge The merge whose tail should be duplicated.
+         * @param replacements A list of replacement {@link PiNode}s, or null. If this is non-null, then the size of the
+         *            list needs to match the number of end nodes at the merge.
+         */
+        public DuplicationOperation(MergeNode merge, List<PiNode> replacements) {
+            this.merge = merge;
+            this.replacements = replacements;
+            this.graph = (StructuredGraph) merge.graph();
+        }
+
+        /**
+         * Performs the actual tail duplication:
+         * <ul>
+         * <li>Creates a new {@link ValueAnchorNode} at the beginning of the duplicated area, an transfers all
+         * dependencies from the merge to this anchor.</li>
+         * <li>Determines the set of fixed nodes to be duplicated.</li>
+         * <li>Creates the new merge at the bottom of the duplicated area.</li>
+         * <li>Determines the complete set of duplicated nodes.</li>
+         * <li>Performs the actual duplication.</li>
+         * </ul>
+         */
+        private void duplicate() {
+            Debug.log("tail duplication at merge %s in %s (prob %f)", merge, graph.method(), merge.probability());
+
+            ValueAnchorNode anchor = addValueAnchor();
+
+            // determine the fixed nodes that should be duplicated (currently: all nodes up until the first control
+            // split, end node, deopt or return.
+            ArrayList<FixedNode> fixedNodes = new ArrayList<>();
+            FixedNode fixed = merge.next();
+            FrameState stateAfter = merge.stateAfter();
+            while (fixed instanceof FixedWithNextNode) {
+                fixedNodes.add(fixed);
+                if (fixed instanceof StateSplit && ((StateSplit) fixed).stateAfter() != null) {
+                    stateAfter = ((StateSplit) fixed).stateAfter();
+                }
+                fixed = ((FixedWithNextNode) fixed).next();
+            }
+
+            EndNode endAfter = createNewMerge(fixed, stateAfter);
+            MergeNode mergeAfter = endAfter.merge();
+            fixedNodes.add(endAfter);
+            final HashSet<Node> duplicatedNodes = buildDuplicatedNodeSet(fixedNodes, stateAfter);
+            mergeAfter.clearEnds();
+            expandDuplicated(duplicatedNodes, mergeAfter);
+            retargetDependencies(duplicatedNodes, anchor);
+
+            List<EndNode> endSnapshot = merge.forwardEnds().snapshot();
+            List<PhiNode> phiSnapshot = merge.phis().snapshot();
+
+            int endIndex = 0;
+            for (final EndNode forwardEnd : merge.forwardEnds()) {
+                Map<Node, Node> duplicates;
+                if (replacements == null || replacements.get(endIndex) == null) {
+                    duplicates = graph.addDuplicates(duplicatedNodes, (DuplicationReplacement) null);
+                } else {
+                    HashMap<Node, Node> replace = new HashMap<>();
+                    replace.put(replacements.get(endIndex).object(), replacements.get(endIndex));
+                    duplicates = graph.addDuplicates(duplicatedNodes, replace);
+                }
+                for (Map.Entry<ValueNode, PhiNode> phi : bottomPhis.entrySet()) {
+                    phi.getValue().initializeValueAt(merge.forwardEndIndex(forwardEnd), (ValueNode) duplicates.get(phi.getKey()));
+                }
+                mergeAfter.addForwardEnd((EndNode) duplicates.get(endAfter));
+
+                // re-wire the duplicated ValueAnchorNode to the predecessor of the corresponding EndNode
+                FixedNode anchorDuplicate = (FixedNode) duplicates.get(anchor);
+                ((FixedWithNextNode) forwardEnd.predecessor()).setNext(anchorDuplicate);
+                // move dependencies on the ValueAnchorNode to the previous BeginNode
+                BeginNode prevBegin = BeginNode.prevBegin(anchorDuplicate);
+                anchorDuplicate.replaceAtUsages(prevBegin);
+
+                // re-wire the phi duplicates to the correct input
+                for (PhiNode phi : phiSnapshot) {
+                    PhiNode phiDuplicate = (PhiNode) duplicates.get(phi);
+                    for (Node usage : phiDuplicate.usages()) {
+                        if (usage instanceof ValueNode) {
+                            ((ValueNode) usage).dependencies().add(prevBegin);
+                        }
+                    }
+                    phiDuplicate.replaceAtUsages(phi.valueAt(forwardEnd));
+                    phiDuplicate.safeDelete();
+                }
+                endIndex++;
+            }
+            GraphUtil.killCFG(merge);
+            for (EndNode forwardEnd : endSnapshot) {
+                forwardEnd.safeDelete();
+            }
+            for (PhiNode phi : phiSnapshot) {
+                // these phis should go away, but they still need to be anchored to a merge to be valid...
+                if (phi.isAlive()) {
+                    phi.setMerge(mergeAfter);
+                }
+            }
+            Debug.dump(graph, "After tail duplication at %s", merge);
+        }
+
+        /**
+         * Inserts a new ValueAnchorNode after the merge and transfers all dependency-usages (not phis) to this
+         * ValueAnchorNode.
+         *
+         * @return The new {@link ValueAnchorNode} that was created.
+         */
+        private ValueAnchorNode addValueAnchor() {
+            ValueAnchorNode anchor = graph.add(new ValueAnchorNode());
+            graph.addAfterFixed(merge, anchor);
+            for (Node usage : merge.usages().snapshot()) {
+                if (usage instanceof PhiNode && ((PhiNode) usage).merge() == merge) {
+                    // nothing to do
+                } else {
+                    usage.replaceFirstInput(merge, anchor);
+                }
+            }
+            return anchor;
+        }
+
+        /**
+         * Given a set of fixed nodes, this method determines the set of fixed and floating nodes that needs to be
+         * duplicated, i.e., all nodes that due to data flow and other dependencies needs to be duplicated.
+         *
+         * @param fixedNodes The set of fixed nodes that should be duplicated.
+         * @param stateAfter The frame state of the merge that follows the set of fixed nodes. All {@link ValueNode}s
+         *            reachable from this state are considered to be reachable from within the duplicated set of nodes.
+         * @return The set of nodes that need to be duplicated.
+         */
+        private HashSet<Node> buildDuplicatedNodeSet(final ArrayList<FixedNode> fixedNodes, FrameState stateAfter) {
+            final NodeBitMap aboveBound = graph.createNodeBitMap();
+            final NodeBitMap belowBound = graph.createNodeBitMap();
+
+            final Deque<Node> worklist = new ArrayDeque<>();
+
+            // Build the set of nodes that have (transitive) usages within the duplicatedNodes.
+            // This is achieved by iterating all nodes that are reachable via inputs from the the fixed nodes.
+            aboveBound.markAll(fixedNodes);
+            worklist.addAll(fixedNodes);
+
+            // the phis at the original merge should always be duplicated
+            for (PhiNode phi : merge.phis()) {
+                aboveBound.mark(phi);
+                worklist.add(phi);
+            }
+
+            NodeClosure<Node> aboveClosure = new NodeClosure<Node>() {
+
+                @Override
+                public void apply(Node usage, Node node) {
+                    if (node instanceof PhiNode && !fixedNodes.contains(((PhiNode) node).merge())) {
+                        // stop iterating: phis belonging to outside merges are known to be outside.
+                    } else if (node instanceof FixedNode) {
+                        // stop iterating: fixed nodes within the given set are traversal roots anyway, and all other
+                        // fixed nodes are known to be outside.
+                    } else if (!aboveBound.isMarked(node)) {
+                        worklist.add(node);
+                        aboveBound.mark(node);
+                    }
+                }
+            };
+
+            if (stateAfter != null) {
+                stateAfter.applyToNonVirtual(aboveClosure);
+            }
+            while (!worklist.isEmpty()) {
+                Node current = worklist.remove();
+                for (Node input : current.inputs()) {
+                    aboveClosure.apply(current, input);
+                }
+            }
+
+            // Build the set of nodes that have (transitive) inputs within the duplicatedNodes.
+            // This is achieved by iterating all nodes that are reachable via usages from the fixed nodes.
+            belowBound.markAll(fixedNodes);
+            worklist.addAll(fixedNodes);
+
+            // the phis at the original merge should always be duplicated
+            for (PhiNode phi : merge.phis()) {
+                belowBound.mark(phi);
+                worklist.add(phi);
+            }
+
+            while (!worklist.isEmpty()) {
+                Node current = worklist.remove();
+                for (Node usage : current.usages()) {
+                    if (usage instanceof PhiNode && !fixedNodes.contains(((PhiNode) usage).merge())) {
+                        // stop iterating: phis belonging to outside merges are known to be outside.
+                    } else if (usage instanceof FixedNode) {
+                        // stop iterating: fixed nodes within the given set are traversal roots anyway, and all other
+                        // fixed nodes are known to be outside.
+                    } else if (!belowBound.isMarked(usage)) {
+                        worklist.add(usage);
+                        belowBound.mark(usage);
+                    }
+                }
+            }
+
+            // build the intersection
+            belowBound.intersect(aboveBound);
+            HashSet<Node> result = new HashSet<>();
+            for (Node node : belowBound) {
+                result.add(node);
+            }
+            return result;
+        }
+
+        /**
+         * Creates a new merge and end node construct at the end of the duplicated area. While it is useless in itself
+         * (merge with only one end) it simplifies the later duplication step.
+         *
+         * @param successor The successor of the duplicated set of nodes, i.e., the first node that should not be
+         *            duplicated.
+         * @param stateAfterMerge The frame state that should be used for the merge.
+         * @return The newly created end node.
+         */
+        private EndNode createNewMerge(FixedNode successor, FrameState stateAfterMerge) {
+            MergeNode newBottomMerge = graph.add(new MergeNode());
+            newBottomMerge.setProbability(successor.probability());
+            EndNode newBottomEnd = graph.add(new EndNode());
+            newBottomMerge.addForwardEnd(newBottomEnd);
+            newBottomMerge.setStateAfter(stateAfterMerge);
+            ((FixedWithNextNode) successor.predecessor()).setNext(newBottomEnd);
+            newBottomMerge.setNext(successor);
+            return newBottomEnd;
+        }
+
+        /**
+         * Expands the set of nodes to be duplicated by looking at a number of conditions:
+         * <ul>
+         * <li>{@link ValueNode}s that have usages on the outside need to be replaced with phis for the outside usages.</li>
+         * <li>Non-{@link ValueNode} nodes that have outside usages (frame states, virtual object states, ...) need to
+         * be cloned immediately for the outside usages.</li>
+         * <li>Nodes that have a {@link StampFactory#extension()} or {@link StampFactory#condition()} stamp need to be
+         * cloned immediately for the outside usages.</li>
+         * <li>Dependencies into the duplicated nodes will be replaced with dependencies on the merge.</li>
+         * <li>Outside non-{@link ValueNode}s with usages within the duplicated set of nodes need to also be duplicated.
+         * </li>
+         * <li>Outside {@link ValueNode}s with {@link StampFactory#extension()} or {@link StampFactory#condition()}
+         * stamps that have usages within the duplicated set of nodes need to also be duplicated.</li>
+         * </ul>
+         *
+         * @param duplicatedNodes The set of duplicated nodes that will be modified (expanded).
+         * @param newBottomMerge The merge that follows the duplicated set of nodes. It will be used for newly created
+         *            phis and to as a target for dependencies that pointed into the duplicated set of nodes.
+         */
+        private void expandDuplicated(HashSet<Node> duplicatedNodes, MergeNode newBottomMerge) {
+            Deque<Node> worklist = new ArrayDeque<>(duplicatedNodes);
+
+            while (!worklist.isEmpty()) {
+                Node duplicated = worklist.remove();
+                if (hasUsagesOutside(duplicated, duplicatedNodes)) {
+                    boolean cloneForOutsideUsages = false;
+                    if (duplicated instanceof ValueNode) {
+                        ValueNode node = (ValueNode) duplicated;
+                        if (node.stamp() == StampFactory.dependency()) {
+                            // re-route dependencies to the merge
+                            replaceUsagesOutside(node, newBottomMerge, duplicatedNodes);
+                            // TODO(ls) maybe introduce phis for dependencies
+                        } else if (node.stamp() == StampFactory.extension() || node.stamp() == StampFactory.condition()) {
+                            cloneForOutsideUsages = true;
+                        } else {
+                            // introduce a new phi
+                            PhiNode newPhi = bottomPhis.get(node);
+                            if (newPhi == null) {
+                                newPhi = graph.add(new PhiNode(node.kind(), newBottomMerge));
+                                bottomPhis.put(node, newPhi);
+                                newPhi.addInput(node);
+                            }
+                            replaceUsagesOutside(node, newPhi, duplicatedNodes);
+                        }
+                    } else {
+                        cloneForOutsideUsages = true;
+                    }
+                    if (cloneForOutsideUsages) {
+                        // clone the offending node to the outside
+                        Node newOutsideClone = duplicated.copyWithInputs();
+                        replaceUsagesOutside(duplicated, newOutsideClone, duplicatedNodes);
+                        // this might cause other nodes to have outside usages, we need to look at those as well
+                        for (Node input : newOutsideClone.inputs()) {
+                            if (duplicatedNodes.contains(input)) {
+                                worklist.add(input);
+                            }
+                        }
+                    }
+                }
+                // check if this node has an input that lies outside and cannot be shared
+                for (Node input : duplicated.inputs()) {
+                    if (!duplicatedNodes.contains(input)) {
+                        boolean duplicateInput = false;
+                        if (input instanceof VirtualState) {
+                            duplicateInput = true;
+                        } else if (input instanceof ValueNode) {
+                            Stamp inputStamp = ((ValueNode) input).stamp();
+                            if (inputStamp == StampFactory.extension() || inputStamp == StampFactory.condition()) {
+                                duplicateInput = true;
+                            }
+                        }
+                        if (duplicateInput) {
+                            duplicatedNodes.add(input);
+                            worklist.add(input);
+                        }
+                    }
+                }
+            }
+        }
+
+        /**
+         * Moves all depdendencies that point outside the duplicated area to the supplied value anchor node.
+         *
+         * @param duplicatedNodes The set of duplicated nodes.
+         * @param anchor The node that will be the new target for all dependencies that point outside the duplicated set of nodes.
+         */
+        private static void retargetDependencies(HashSet<Node> duplicatedNodes, ValueAnchorNode anchor) {
+            for (Node node : duplicatedNodes) {
+                if (node instanceof ValueNode) {
+                    NodeInputList<ValueNode> dependencies = ((ValueNode) node).dependencies();
+                    for (int i = 0; i < dependencies.size(); i++) {
+                        Node dependency = dependencies.get(i);
+                        if (dependency != null && !duplicatedNodes.contains(dependency)) {
+                            Debug.log("retargeting dependency %s to %s on %s", dependency, anchor, node);
+                            dependencies.set(i, anchor);
+                        }
+                    }
+                }
+            }
+        }
+
+        /**
+         * Checks if the given node has usages that are not within the given set of nodes.
+         *
+         * @param node The node whose usages are checked.
+         * @param nodeSet The set of nodes that are considered to be "within".
+         * @return true if the given node has usages on the outside, false otherwise.
+         */
+        private static boolean hasUsagesOutside(Node node, HashSet<Node> nodeSet) {
+            for (Node usage : node.usages()) {
+                if (!nodeSet.contains(usage)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        /**
+         * Replaces the given node with the given replacement at all usages that are not within the given set of nodes.
+         *
+         * @param node The node to be replaced at outside usages.
+         * @param replacement The node that replaced the given node at outside usages.
+         * @param nodeSet The set of nodes that are considered to be "within".
+         */
+        private static void replaceUsagesOutside(Node node, Node replacement, HashSet<Node> nodeSet) {
+            for (Node usage : node.usages().snapshot()) {
+                if (!nodeSet.contains(usage)) {
+                    usage.replaceFirstInput(node, replacement);
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/BlockClosure.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.phases.schedule;
+
+import com.oracle.graal.lir.cfg.*;
+
+/**
+ * The {@code BlockClosure} interface represents a closure for iterating over blocks.
+ */
+public interface BlockClosure {
+    void apply(Block block);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,399 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.phases.schedule;
+
+import java.util.*;
+
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.Node.Verbosity;
+import com.oracle.graal.lir.cfg.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.virtual.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.phases.*;
+
+public class SchedulePhase extends Phase {
+    private ControlFlowGraph cfg;
+    private NodeMap<Block> earliestCache;
+
+    /**
+     * Map from blocks to the nodes in each block.
+     */
+    private BlockMap<List<ScheduledNode>> blockToNodesMap;
+
+    public SchedulePhase() {
+        super("Schedule");
+    }
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        cfg = ControlFlowGraph.compute(graph, true, true, true, false);
+        earliestCache = graph.createNodeMap();
+        blockToNodesMap = new BlockMap<>(cfg);
+
+        assignBlockToNodes(graph);
+        sortNodesWithinBlocks(graph);
+    }
+
+    /**
+     * Sets {@link ScheduledNode#scheduledNext} on all scheduled nodes in all blocks using the scheduling built by @link {@link #run(StructuredGraph)}.
+     * This method should thus only be called when run has been successfully executed.
+     */
+    public void scheduleGraph() {
+        assert blockToNodesMap != null : "cannot set scheduledNext before run has been executed";
+        for (Block block : cfg.getBlocks()) {
+            List<ScheduledNode> nodeList = blockToNodesMap.get(block);
+            ScheduledNode last = null;
+            for (ScheduledNode node : nodeList) {
+                if (last != null) {
+                    last.setScheduledNext(node);
+                }
+                last = node;
+            }
+        }
+    }
+
+    public ControlFlowGraph getCFG() {
+        return cfg;
+    }
+
+    /**
+     * Gets the map from each block to the nodes in the block.
+     */
+    public BlockMap<List<ScheduledNode>> getBlockToNodesMap() {
+        return blockToNodesMap;
+    }
+
+    /**
+     * Gets the nodes in a given block.
+     */
+    public List<ScheduledNode> nodesFor(Block block) {
+        return blockToNodesMap.get(block);
+    }
+
+    private void assignBlockToNodes(StructuredGraph graph) {
+        for (Block block : cfg.getBlocks()) {
+            List<ScheduledNode> nodes = new ArrayList<>();
+            assert blockToNodesMap.get(block) == null;
+            blockToNodesMap.put(block, nodes);
+            for (FixedNode node : block.getNodes()) {
+                nodes.add(node);
+            }
+        }
+
+        for (Node n : graph.getNodes()) {
+            if (n instanceof ScheduledNode) {
+                assignBlockToNode((ScheduledNode) n);
+            }
+        }
+    }
+
+    /**
+     * Assigns a block to the given node. This method expects that PhiNodes and FixedNodes are already assigned to a block.
+     */
+    private void assignBlockToNode(ScheduledNode node) {
+        assert !node.isDeleted();
+
+        Block prevBlock = cfg.getNodeToBlock().get(node);
+        if (prevBlock != null) {
+            return;
+        }
+        // PhiNodes and FixedNodes should already have been placed in blocks by ControlFlowGraph.identifyBlocks
+        assert !(node instanceof PhiNode) : node;
+        assert !(node instanceof FixedNode) : node;
+        // if in CFG, schedule at the latest position possible in the outermost loop possible
+        Block latestBlock = latestBlock(node);
+        Block block;
+        if (latestBlock == null) {
+            block = earliestBlock(node);
+        } else if (GraalOptions.ScheduleOutOfLoops && !(node instanceof VirtualObjectNode)) {
+            Block earliestBlock = earliestBlock(node);
+            block = scheduleOutOfLoops(node, latestBlock, earliestBlock);
+            assert earliestBlock.dominates(block) : "Graph can not be scheduled : inconsistent for " + node + " (" + earliestBlock + " needs to dominate " + block + ")";
+        } else {
+            block = latestBlock;
+        }
+        cfg.getNodeToBlock().set(node, block);
+        blockToNodesMap.get(block).add(node);
+    }
+
+    /**
+     * Calculates the last block that the given node could be scheduled in, i.e., the common dominator of all usages.
+     * To do so all usages are also assigned to blocks.
+     */
+    private Block latestBlock(ScheduledNode node) {
+        CommonDominatorBlockClosure cdbc = new CommonDominatorBlockClosure(null);
+        for (Node succ : node.successors().nonNull()) {
+            assert cfg.getNodeToBlock().get(succ) != null;
+            cdbc.apply(cfg.getNodeToBlock().get(succ));
+        }
+        ensureScheduledUsages(node);
+        for (Node usage : node.usages()) {
+            blocksForUsage(node, usage, cdbc);
+        }
+        return cdbc.block;
+    }
+
+    /**
+     * A closure that will calculate the common dominator of all blocks passed to its {@link #apply(Block)} method.
+     */
+    private static class CommonDominatorBlockClosure implements BlockClosure {
+        public Block block;
+        public CommonDominatorBlockClosure(Block block) {
+            this.block = block;
+        }
+        @Override
+        public void apply(Block newBlock) {
+            this.block = getCommonDominator(this.block, newBlock);
+        }
+    }
+
+    /**
+     * Determines the earliest block in which the given node can be scheduled.
+     */
+    private Block earliestBlock(Node node) {
+        Block earliest = cfg.getNodeToBlock().get(node);
+        if (earliest != null) {
+            return earliest;
+        }
+        earliest = earliestCache.get(node);
+        if (earliest != null) {
+            return earliest;
+        }
+        /*
+         * All inputs must be in a dominating block, otherwise the graph cannot be scheduled. This implies that the
+         * inputs' blocks have a total ordering via their dominance relation. So in order to find the earliest block
+         * placement for this node we need to find the input block that is dominated by all other input blocks.
+         *
+         * While iterating over the inputs a set of dominator blocks of the current earliest placement is maintained.
+         * When the block of an input is not within this set, it becomes the current earliest placement and the list of
+         * dominator blocks is updated.
+         */
+        BitSet dominators = new BitSet(cfg.getBlocks().length);
+
+        assert node.predecessor() == null;
+        for (Node input : node.inputs().nonNull()) {
+            assert input instanceof ValueNode;
+            Block inputEarliest = earliestBlock(input);
+            if (!dominators.get(inputEarliest.getId())) {
+                earliest = inputEarliest;
+                do {
+                    dominators.set(inputEarliest.getId());
+                    inputEarliest = inputEarliest.getDominator();
+                } while(inputEarliest != null && !dominators.get(inputEarliest.getId()));
+            }
+        }
+        if (earliest == null) {
+            earliest = cfg.getStartBlock();
+        }
+        earliestCache.set(node, earliest);
+        return earliest;
+    }
+
+
+    private static Block scheduleOutOfLoops(Node n, Block latestBlock, Block earliest) {
+        assert latestBlock != null : "no latest : " + n;
+        Block cur = latestBlock;
+        Block result = latestBlock;
+        while (cur.getLoop() != null && cur != earliest && cur.getDominator() != null) {
+            Block dom = cur.getDominator();
+            if (dom.getLoopDepth() < result.getLoopDepth()) {
+                result = dom;
+            }
+            cur = dom;
+        }
+        return result;
+    }
+
+    /**
+     * Passes all blocks that a specific usage of a node is in to a given closure.
+     * This is more complex than just taking the usage's block because of of PhiNodes and FrameStates.
+     *
+     * @param node the node that needs to be scheduled
+     * @param usage the usage whose blocks need to be considered
+     * @param closure the closure that will be called for each block
+     */
+    private void blocksForUsage(ScheduledNode node, Node usage, BlockClosure closure) {
+        assert !(node instanceof PhiNode);
+
+        if (usage instanceof PhiNode) {
+            // An input to a PhiNode is used at the end of the predecessor block that corresponds to the PhiNode input.
+            // One PhiNode can use an input multiple times, the closure will be called for each usage.
+            PhiNode phi = (PhiNode) usage;
+            MergeNode merge = phi.merge();
+            Block mergeBlock = cfg.getNodeToBlock().get(merge);
+            assert mergeBlock != null : "no block for merge " + merge.toString(Verbosity.Id);
+            for (int i = 0; i < phi.valueCount(); ++i) {
+                if (phi.valueAt(i) == node) {
+                    if (mergeBlock.getPredecessors().size() <= i) {
+                        TTY.println(merge.toString());
+                        TTY.println(phi.toString());
+                        TTY.println(merge.cfgPredecessors().toString());
+                        TTY.println(mergeBlock.getPredecessors().toString());
+                        TTY.println(phi.inputs().toString());
+                        TTY.println("value count: " + phi.valueCount());
+                    }
+                    closure.apply(mergeBlock.getPredecessors().get(i));
+                }
+            }
+        } else if (usage instanceof VirtualState) {
+            // The following logic does not work if node is a PhiNode, but this method is never called for PhiNodes.
+            for (Node unscheduledUsage : usage.usages()) {
+                if (unscheduledUsage instanceof VirtualState) {
+                    // If a FrameState is an outer FrameState this method behaves as if the inner FrameState was the actual usage, by recursing.
+                    blocksForUsage(node, unscheduledUsage, closure);
+                } else if (unscheduledUsage instanceof MergeNode) {
+                    // Only FrameStates can be connected to MergeNodes.
+                    assert usage instanceof FrameState;
+                    // If a FrameState belongs to a MergeNode then it's inputs will be placed at the common dominator of all EndNodes.
+                    for (Node pred : unscheduledUsage.cfgPredecessors()) {
+                        closure.apply(cfg.getNodeToBlock().get(pred));
+                    }
+                } else {
+                    // For the time being, only FrameStates can be connected to StateSplits.
+                    assert usage instanceof FrameState;
+                    assert unscheduledUsage instanceof StateSplit;
+                    // Otherwise: Put the input into the same block as the usage.
+                    assignBlockToNode((ScheduledNode) unscheduledUsage);
+                    closure.apply(cfg.getNodeToBlock().get(unscheduledUsage));
+                }
+            }
+        } else {
+            // All other types of usages: Put the input into the same block as the usage.
+            assignBlockToNode((ScheduledNode) usage);
+            closure.apply(cfg.getNodeToBlock().get(usage));
+        }
+    }
+
+    private void ensureScheduledUsages(Node node) {
+        for (Node usage : node.usages().filter(ScheduledNode.class)) {
+            assignBlockToNode((ScheduledNode) usage);
+        }
+        // now true usages are ready
+    }
+
+    private static Block getCommonDominator(Block a, Block b) {
+        if (a == null) {
+            return b;
+        }
+        if (b == null) {
+            return a;
+        }
+        return ControlFlowGraph.commonDominator(a, b);
+    }
+
+    private void sortNodesWithinBlocks(StructuredGraph graph) {
+        NodeBitMap visited = graph.createNodeBitMap();
+        for (Block b : cfg.getBlocks()) {
+            sortNodesWithinBlock(b, visited);
+        }
+    }
+
+    /**
+     * Sorts the nodes within a block by adding the nodes to a list in a post-order iteration over all inputs.
+     * This means that a node is added to the list after all its inputs have been processed.
+     */
+    private void sortNodesWithinBlock(Block b, NodeBitMap visited) {
+        List<ScheduledNode> instructions = blockToNodesMap.get(b);
+        List<ScheduledNode> sortedInstructions = new ArrayList<>(instructions.size() + 2);
+
+        assert !visited.isMarked(b.getBeginNode()) && cfg.blockFor(b.getBeginNode()) == b;
+        assert !visited.isMarked(b.getEndNode()) && cfg.blockFor(b.getEndNode()) == b;
+
+        for (ScheduledNode i : instructions) {
+            addToSorting(b, i, sortedInstructions, visited);
+        }
+
+        // Make sure that last node gets really last (i.e. when a frame state successor hangs off it).
+        Node lastSorted = sortedInstructions.get(sortedInstructions.size() - 1);
+        if (lastSorted != b.getEndNode()) {
+            int idx = sortedInstructions.indexOf(b.getEndNode());
+            boolean canNotMove = false;
+            for (int i = idx + 1; i < sortedInstructions.size(); i++) {
+                if (sortedInstructions.get(i).inputs().contains(b.getEndNode())) {
+                    canNotMove = true;
+                    break;
+                }
+            }
+            if (canNotMove) {
+                if (b.getEndNode() instanceof ControlSplitNode) {
+                    throw new GraalInternalError("Schedule is not possible : needs to move a node after the last node of the block which can not be move").
+                    addContext(lastSorted).
+                    addContext(b.getEndNode());
+                }
+
+                //b.setLastNode(lastSorted);
+            } else {
+                sortedInstructions.remove(b.getEndNode());
+                sortedInstructions.add(b.getEndNode());
+            }
+        }
+        blockToNodesMap.put(b, sortedInstructions);
+    }
+
+    private void addUnscheduledToSorting(Block b, VirtualState state, List<ScheduledNode> sortedInstructions, NodeBitMap visited) {
+        if (state != null) {
+            // UnscheduledNodes should never be marked as visited.
+            assert !visited.isMarked(state);
+
+            for (Node input : state.inputs()) {
+                if (input instanceof VirtualState) {
+                    addUnscheduledToSorting(b, (VirtualState) input, sortedInstructions, visited);
+                } else {
+                    addToSorting(b, (ScheduledNode) input, sortedInstructions, visited);
+                }
+            }
+        }
+    }
+
+    private void addToSorting(Block b, ScheduledNode i, List<ScheduledNode> sortedInstructions, NodeBitMap visited) {
+        if (i == null || visited.isMarked(i) || cfg.getNodeToBlock().get(i) != b || i instanceof PhiNode || i instanceof LocalNode) {
+            return;
+        }
+
+        FrameState state = null;
+        WriteNode write = null;
+        for (Node input : i.inputs()) {
+            if (input instanceof WriteNode && !visited.isMarked(input) && cfg.getNodeToBlock().get(input) == b) {
+                assert write == null;
+                write = (WriteNode) input;
+            } else if (input instanceof FrameState) {
+                assert state == null;
+                state = (FrameState) input;
+            } else {
+                addToSorting(b, (ScheduledNode) input, sortedInstructions, visited);
+            }
+        }
+
+        addToSorting(b, (ScheduledNode) i.predecessor(), sortedInstructions, visited);
+        visited.mark(i);
+        addUnscheduledToSorting(b, state, sortedInstructions, visited);
+        assert write == null || !visited.isMarked(write);
+        addToSorting(b, write, sortedInstructions, visited);
+
+        // Now predecessors and inputs are scheduled => we can add this node.
+        sortedInstructions.add(i);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/ArrayMap.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.phases.util;
+
+/**
+ * The {@code ArrayMap} class implements an efficient one-level map which is implemented
+ * as an array. Note that because of the one-level array inside, this data structure performs best
+ * when the range of integer keys is small and densely used. Note that the implementation can
+ * handle arbitrary intervals, including negative numbers, up to intervals of size 2^31 - 1.
+ */
+public class ArrayMap<T> {
+
+    private static final int INITIAL_SIZE = 5; // how big the initial array should be
+    private static final int EXTRA = 2; // how far on the left or right of a new element to grow
+
+    Object[] map;
+    int low;
+
+    /**
+     * Constructs a new {@code ArrayMap} with no initial assumptions.
+     */
+    public ArrayMap() {
+    }
+
+    /**
+     * Constructs a new {@code ArrayMap} that initially covers the specified interval.
+     * Note that this map will automatically expand if necessary later.
+     * @param low the low index, inclusive
+     * @param high the high index, exclusive
+     */
+    public ArrayMap(int low, int high) {
+        this.low = low;
+        this.map = new Object[high - low + 1];
+    }
+
+    /**
+     * Puts a new value in the map at the specified index.
+     * @param i the index at which to store the value
+     * @param value the value to store at the specified index
+     */
+    public void put(int i, T value) {
+        int index = i - low;
+        if (map == null) {
+            // no map yet
+            map = new Object[INITIAL_SIZE];
+            low = index - 2;
+            map[INITIAL_SIZE / 2] = value;
+        } else if (index < 0) {
+            // grow backwards
+            growBackward(i, value);
+        } else if (index >= map.length) {
+            // grow forwards
+            growForward(i, value);
+        } else {
+            // no growth necessary
+            map[index] = value;
+        }
+    }
+
+    /**
+     * Gets the value at the specified index in the map.
+     * @param i the index
+     * @return the value at the specified index; {@code null} if there is no value at the specified index,
+     * or if the index is out of the currently stored range
+     */
+    public T get(int i) {
+        int index = i - low;
+        if (map == null || index < 0 || index >= map.length) {
+            return null;
+        }
+        Class<T> type = null;
+        return Util.uncheckedCast(type, map[index]);
+    }
+
+    public int length() {
+        return map.length;
+    }
+
+    private void growBackward(int i, T value) {
+        int nlow = i - EXTRA;
+        Object[] nmap = new Object[low - nlow + map.length];
+        System.arraycopy(map, 0, nmap, low - nlow, map.length);
+        map = nmap;
+        low = nlow;
+        map[i - low] = value;
+    }
+
+    private void growForward(int i, T value) {
+        int nlen = i - low + 1 + EXTRA;
+        Object[] nmap = new Object[nlen];
+        System.arraycopy(map, 0, nmap, 0, map.length);
+        map = nmap;
+        map[i - low] = value;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/BitMap2D.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.phases.util;
+
+import java.util.*;
+
+/**
+ * This class implements a two-dimensional bitmap.
+ */
+public final class BitMap2D {
+
+    private BitSet map;
+    private final int bitsPerSlot;
+
+    private int bitIndex(int slotIndex, int bitWithinSlotIndex)  {
+      return slotIndex * bitsPerSlot + bitWithinSlotIndex;
+    }
+
+    private boolean verifyBitWithinSlotIndex(int index)  {
+      assert index < bitsPerSlot : "index " + index + " is out of bounds " + bitsPerSlot;
+      return true;
+    }
+
+    public BitMap2D(int sizeInSlots, int bitsPerSlot) {
+        map = new BitSet(sizeInSlots * bitsPerSlot);
+        this.bitsPerSlot = bitsPerSlot;
+    }
+
+    public int sizeInBits() {
+      return map.size();
+    }
+
+    // Returns number of full slots that have been allocated
+    public int sizeInSlots() {
+      return map.size() / bitsPerSlot;
+    }
+
+    public boolean isValidIndex(int slotIndex, int bitWithinSlotIndex) {
+      assert verifyBitWithinSlotIndex(bitWithinSlotIndex);
+      return (bitIndex(slotIndex, bitWithinSlotIndex) < sizeInBits());
+    }
+
+    public boolean at(int slotIndex, int bitWithinSlotIndex)  {
+      assert verifyBitWithinSlotIndex(bitWithinSlotIndex);
+      return map.get(bitIndex(slotIndex, bitWithinSlotIndex));
+    }
+
+    public void setBit(int slotIndex, int bitWithinSlotIndex) {
+      assert verifyBitWithinSlotIndex(bitWithinSlotIndex);
+      map.set(bitIndex(slotIndex, bitWithinSlotIndex));
+    }
+
+    public void clearBit(int slotIndex, int bitWithinSlotIndex) {
+      assert verifyBitWithinSlotIndex(bitWithinSlotIndex);
+      map.clear(bitIndex(slotIndex, bitWithinSlotIndex));
+    }
+
+    public void atPutGrow(int slotIndex, int bitWithinSlotIndex, boolean value) {
+       int size = sizeInSlots();
+       if (size <= slotIndex) {
+           while (size <= slotIndex) {
+               size *= 2;
+           }
+           BitSet newBitMap = new BitSet(size * bitsPerSlot);
+           newBitMap.or(map);
+           map = newBitMap;
+       }
+
+       if (value) {
+           setBit(slotIndex, bitWithinSlotIndex);
+       } else {
+           clearBit(slotIndex, bitWithinSlotIndex);
+       }
+    }
+
+    public void clear() {
+        map.clear();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/BlockWorkList.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.phases.util;
+
+import com.oracle.graal.nodes.*;
+
+/**
+ * This class implements a worklist for dealing with blocks. The worklist can
+ * operate either as a stack (i.e. first-in / last-out), or as a sorted list,
+ * where blocks can be sorted by a supplied number. The latter usage lends itself
+ * naturally to iterative dataflow analysis problems.
+ */
+public class BlockWorkList {
+    MergeNode[] workList;
+    int[] workListNumbers;
+    int workListIndex;
+
+    /**
+     * Adds a block to this list in an unsorted fashion, like a stack.
+     * @param block the block to add
+     */
+    public void add(MergeNode block) {
+        if (workList == null) {
+            // worklist not allocated yet
+            allocate();
+        } else if (workListIndex == workList.length) {
+            // need to grow the worklist
+            grow();
+        }
+        // put the block at the end of the array
+        workList[workListIndex++] = block;
+    }
+
+    /**
+     * Adds a block to this list, sorted by the supplied number. The block
+     * with the lowest number is returned upon subsequent removes.
+     * @param block the block to add
+     * @param number the number used to sort the block
+     */
+    public void addSorted(MergeNode block, int number) {
+        if (workList == null) {
+            // worklist not allocated yet
+            allocate();
+        } else if (workListIndex == workList.length) {
+            // need to grow the worklist
+            grow();
+        }
+        // put the block at the end of the array
+        workList[workListIndex] = block;
+        workListNumbers[workListIndex] = number;
+        workListIndex++;
+        int i = workListIndex - 2;
+        // push block towards the beginning of the array
+        for (; i >= 0; i--) {
+            int n = workListNumbers[i];
+            if (n >= number) {
+                break; // already in the right position
+            }
+            workList[i + 1] = workList[i]; // bubble b down by one
+            workList[i] = block;           // and overwrite its place with block
+            workListNumbers[i + 1] = n;    // bubble n down by one
+            workListNumbers[i] = number;   // and overwrite its place with number
+        }
+    }
+
+    /**
+     * Removes the next block from this work list. If the blocks have been added
+     * in a sorted order, then the block with the lowest number is returned. Otherwise,
+     * the last block added is returned.
+     * @return the next block in the list
+     */
+    public MergeNode removeFromWorkList() {
+        if (workListIndex != 0) {
+            return workList[--workListIndex];
+        }
+        return null;
+    }
+
+    /**
+     * Checks whether the list is empty.
+     * @return {@code true} if this list is empty
+     */
+    public boolean isEmpty() {
+        return workListIndex == 0;
+    }
+
+    private void allocate() {
+        workList = new MergeNode[5];
+        workListNumbers = new int[5];
+    }
+
+    private void grow() {
+        int prevLength = workList.length;
+        MergeNode[] nworkList = new MergeNode[prevLength * 3];
+        System.arraycopy(workList, 0, nworkList, 0, prevLength);
+        workList = nworkList;
+
+        int[] nworkListNumbers = new int[prevLength * 3];
+        System.arraycopy(workListNumbers, 0, nworkListNumbers, 0, prevLength);
+        workListNumbers = nworkListNumbers;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,141 @@
+/*
+ * 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 com.oracle.graal.phases.util;
+
+import java.util.*;
+
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+
+public class GraphOrder implements Iterable<Node> {
+
+    private final ArrayList<Node> nodes = new ArrayList<>();
+
+    private GraphOrder() {
+    }
+
+    public GraphOrder(Graph graph) {
+        NodeBitMap visited = graph.createNodeBitMap();
+
+        for (ReturnNode node : graph.getNodes(ReturnNode.class)) {
+            visitForward(visited, node);
+        }
+        for (UnwindNode node : graph.getNodes(UnwindNode.class)) {
+            visitForward(visited, node);
+        }
+        for (DeoptimizeNode node : graph.getNodes(DeoptimizeNode.class)) {
+            visitForward(visited, node);
+        }
+    }
+
+    public static GraphOrder forwardGraph(Graph graph) {
+        GraphOrder result = new GraphOrder();
+
+        NodeBitMap visited = graph.createNodeBitMap();
+
+        for (ReturnNode node : graph.getNodes(ReturnNode.class)) {
+            result.visitForward(visited, node);
+        }
+        for (UnwindNode node : graph.getNodes(UnwindNode.class)) {
+            result.visitForward(visited, node);
+        }
+        for (DeoptimizeNode node : graph.getNodes(DeoptimizeNode.class)) {
+            result.visitForward(visited, node);
+        }
+        return result;
+    }
+
+    public static GraphOrder backwardGraph(Graph graph) {
+        GraphOrder result = new GraphOrder();
+
+        NodeBitMap visited = graph.createNodeBitMap();
+
+        for (Node node : forwardGraph(graph)) {
+            result.visitBackward(visited, node);
+        }
+        return result;
+    }
+
+    private void visitForward(NodeBitMap visited, Node node) {
+        if (node != null && !visited.isMarked(node)) {
+            visited.mark(node);
+            if (node.predecessor() != null) {
+                visitForward(visited, node.predecessor());
+            }
+            if (node instanceof MergeNode) {
+                // make sure that the cfg predecessors of a MergeNode are processed first
+                MergeNode merge = (MergeNode) node;
+                for (int i = 0; i < merge.forwardEndCount(); i++) {
+                    visitForward(visited, merge.forwardEndAt(i));
+                }
+            }
+            for (Node input : node.inputs()) {
+                visitForward(visited, input);
+            }
+            nodes.add(node);
+        }
+    }
+
+    private void visitBackward(NodeBitMap visited, Node node) {
+        if (node != null && !visited.isMarked(node)) {
+            visited.mark(node);
+            for (Node successor : node.successors()) {
+                visitBackward(visited, successor);
+            }
+            for (Node usage : node.usages()) {
+                visitBackward(visited, usage);
+            }
+            nodes.add(node);
+        }
+    }
+
+    @Override
+    public Iterator<Node> iterator() {
+        return new Iterator<Node>() {
+
+            private int pos = 0;
+
+            private void removeDeleted() {
+                while (pos < nodes.size() && nodes.get(pos).isDeleted()) {
+                    pos++;
+                }
+            }
+
+            @Override
+            public boolean hasNext() {
+                removeDeleted();
+                return pos < nodes.size();
+            }
+
+            @Override
+            public Node next() {
+                return nodes.get(pos++);
+            }
+
+            @Override
+            public void remove() {
+                throw new UnsupportedOperationException();
+            }
+        };
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/InliningUtil.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,960 @@
+/*
+ * Copyright (c) 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 com.oracle.graal.phases.util;
+
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.meta.JavaType.Representation;
+import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.FrameState.InliningIdentifier;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.phases.*;
+
+public class InliningUtil {
+
+    private static final DebugMetric metricInliningTailDuplication = Debug.metric("InliningTailDuplication");
+
+    public interface InliningCallback {
+        StructuredGraph buildGraph(ResolvedJavaMethod method);
+        double inliningWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke);
+        void recordMethodContentsAssumption(ResolvedJavaMethod method);
+        void recordConcreteMethodAssumption(ResolvedJavaMethod method, ResolvedJavaType context, ResolvedJavaMethod impl);
+    }
+
+    public static String methodName(ResolvedJavaMethod method, Invoke invoke) {
+        if (!Debug.isLogEnabled()) {
+            return null;
+        } else if (invoke != null && invoke.stateAfter() != null) {
+            return methodName(invoke.stateAfter(), invoke.bci()) + ": " + MetaUtil.format("%H.%n(%p):%r", method) + " (" + method.codeSize() + " bytes)";
+        } else {
+            return MetaUtil.format("%H.%n(%p):%r", method) + " (" + method.codeSize() + " bytes)";
+        }
+    }
+
+    public static String methodName(InlineInfo info) {
+        if (!Debug.isLogEnabled()) {
+            return null;
+        } else if (info.invoke != null && info.invoke.stateAfter() != null) {
+            return methodName(info.invoke.stateAfter(), info.invoke.bci()) + ": " + info.toString();
+        } else {
+            return info.toString();
+        }
+    }
+
+    private static String methodName(FrameState frameState, int bci) {
+        StringBuilder sb = new StringBuilder();
+        if (frameState.outerFrameState() != null) {
+            sb.append(methodName(frameState.outerFrameState(), frameState.outerFrameState().bci));
+            sb.append("->");
+        }
+        sb.append(MetaUtil.format("%h.%n", frameState.method()));
+        sb.append("@").append(bci);
+        return sb.toString();
+    }
+
+    /**
+     * Represents an opportunity for inlining at the given invoke, with the given weight and level.
+     * The weight is the amortized weight of the additional code - so smaller is better.
+     * The level is the number of nested inlinings that lead to this invoke.
+     */
+    public abstract static class InlineInfo implements Comparable<InlineInfo> {
+        public final Invoke invoke;
+        public final double weight;
+        public final int level;
+
+        public InlineInfo(Invoke invoke, double weight, int level) {
+            this.invoke = invoke;
+            this.weight = weight;
+            this.level = level;
+        }
+
+        public abstract int compiledCodeSize();
+
+        @Override
+        public int compareTo(InlineInfo o) {
+            return (weight < o.weight) ? -1 : (weight > o.weight) ? 1 : 0;
+        }
+
+        protected static StructuredGraph getGraph(final ResolvedJavaMethod concrete, final InliningCallback callback) {
+            return Debug.scope("GetInliningGraph", concrete, new Callable<StructuredGraph>() {
+                @Override
+                public StructuredGraph call() throws Exception {
+                    return callback.buildGraph(concrete);
+                }
+            });
+        }
+
+        public abstract boolean canDeopt();
+
+        /**
+         * Performs the inlining described by this object and returns the node that represents the return value of the
+         * inlined method (or null for void methods and methods that have no non-exceptional exit).
+         *
+         * @param graph
+         * @param runtime
+         * @param callback
+         */
+        public abstract void inline(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback);
+    }
+
+    /**
+     * Represents an inlining opportunity where the compiler can statically determine a monomorphic target method and
+     * therefore is able to determine the called method exactly.
+     */
+    private static class ExactInlineInfo extends InlineInfo {
+        public final ResolvedJavaMethod concrete;
+
+        public ExactInlineInfo(Invoke invoke, double weight, int level, ResolvedJavaMethod concrete) {
+            super(invoke, weight, level);
+            this.concrete = concrete;
+        }
+
+        @Override
+        public void inline(StructuredGraph compilerGraph, GraalCodeCacheProvider runtime, final InliningCallback callback) {
+            StructuredGraph graph = getGraph(concrete, callback);
+            assert !IntrinsificationPhase.canIntrinsify(invoke, concrete, runtime);
+            callback.recordMethodContentsAssumption(concrete);
+            InliningUtil.inline(invoke, graph, true);
+        }
+
+        @Override
+        public int compiledCodeSize() {
+            return concrete.compiledCodeSize();
+        }
+
+        @Override
+        public String toString() {
+            return "exact " + MetaUtil.format("%H.%n(%p):%r", concrete);
+        }
+
+        @Override
+        public boolean canDeopt() {
+            return false;
+        }
+    }
+
+    /**
+     * Represents an inlining opportunity for which profiling information suggests a monomorphic receiver, but for which
+     * the receiver type cannot be proven. A type check guard will be generated if this inlining is performed.
+     */
+    private static class TypeGuardInlineInfo extends InlineInfo {
+        public final ResolvedJavaMethod concrete;
+        public final ResolvedJavaType type;
+
+        public TypeGuardInlineInfo(Invoke invoke, double weight, int level, ResolvedJavaMethod concrete, ResolvedJavaType type) {
+            super(invoke, weight, level);
+            this.concrete = concrete;
+            this.type = type;
+        }
+
+        @Override
+        public int compiledCodeSize() {
+            return concrete.compiledCodeSize();
+        }
+
+        @Override
+        public void inline(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback) {
+            // receiver null check must be before the type check
+            InliningUtil.receiverNullCheck(invoke);
+            ValueNode receiver = invoke.methodCallTarget().receiver();
+            LoadHubNode receiverHub = graph.add(new LoadHubNode(receiver));
+            ConstantNode typeHub = ConstantNode.forConstant(type.getEncoding(Representation.ObjectHub), runtime, graph);
+            ObjectEqualsNode typeCheck = graph.unique(new ObjectEqualsNode(receiverHub, typeHub));
+            FixedGuardNode guard = graph.add(new FixedGuardNode(typeCheck, DeoptimizationReason.TypeCheckedInliningViolated, DeoptimizationAction.InvalidateReprofile, invoke.leafGraphId()));
+            ValueAnchorNode anchor = graph.add(new ValueAnchorNode());
+            assert invoke.predecessor() != null;
+
+            ValueNode anchoredReceiver = createAnchoredReceiver(graph, anchor, type, receiver, true);
+            invoke.callTarget().replaceFirstInput(receiver, anchoredReceiver);
+
+            graph.addBeforeFixed(invoke.node(), receiverHub);
+            graph.addBeforeFixed(invoke.node(), guard);
+            graph.addBeforeFixed(invoke.node(), anchor);
+
+            StructuredGraph calleeGraph = getGraph(concrete, callback);
+            assert !IntrinsificationPhase.canIntrinsify(invoke, concrete, runtime);
+            callback.recordMethodContentsAssumption(concrete);
+            InliningUtil.inline(invoke, calleeGraph, false);
+        }
+
+        @Override
+        public String toString() {
+            return "type-checked " + MetaUtil.format("%H.%n(%p):%r", concrete);
+        }
+
+        @Override
+        public boolean canDeopt() {
+            return true;
+        }
+    }
+
+    /**
+     * Polymorphic inlining of m methods with n type checks (n >= m) in case that the profiling information suggests a reasonable
+     * amounts of different receiver types and different methods. If an unknown type is encountered a deoptimization is triggered.
+     */
+    private static class MultiTypeGuardInlineInfo extends InlineInfo {
+        public final List<ResolvedJavaMethod> concretes;
+        public final ProfiledType[] ptypes;
+        public final int[] typesToConcretes;
+        public final double notRecordedTypeProbability;
+
+        public MultiTypeGuardInlineInfo(Invoke invoke, double weight, int level, List<ResolvedJavaMethod> concretes, ProfiledType[] ptypes,
+                        int[] typesToConcretes, double notRecordedTypeProbability) {
+            super(invoke, weight, level);
+            assert concretes.size() > 0 && concretes.size() <= ptypes.length : "must have at least one method but no more than types methods";
+            assert ptypes.length == typesToConcretes.length : "array lengths must match";
+
+            this.concretes = concretes;
+            this.ptypes = ptypes;
+            this.typesToConcretes = typesToConcretes;
+            this.notRecordedTypeProbability = notRecordedTypeProbability;
+        }
+
+        @Override
+        public int compiledCodeSize() {
+            int result = 0;
+            for (ResolvedJavaMethod m: concretes) {
+                result += m.compiledCodeSize();
+            }
+            return result;
+        }
+
+        @Override
+        public void inline(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback) {
+            int numberOfMethods = concretes.size();
+            boolean hasReturnValue = invoke.node().kind() != Kind.Void;
+
+            // receiver null check must be the first node
+            InliningUtil.receiverNullCheck(invoke);
+            if (numberOfMethods > 1 || shouldFallbackToInvoke()) {
+                inlineMultipleMethods(graph, runtime, callback, numberOfMethods, hasReturnValue);
+            } else {
+                inlineSingleMethod(graph, runtime, callback);
+            }
+        }
+
+        private boolean shouldFallbackToInvoke() {
+            return notRecordedTypeProbability > 0;
+        }
+
+        private void inlineMultipleMethods(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback, int numberOfMethods, boolean hasReturnValue) {
+            FixedNode continuation = invoke.next();
+
+            ValueNode originalReceiver = invoke.methodCallTarget().receiver();
+            // setup merge and phi nodes for results and exceptions
+            MergeNode returnMerge = graph.add(new MergeNode());
+            returnMerge.setProbability(invoke.probability());
+            returnMerge.setStateAfter(invoke.stateAfter().duplicate(invoke.stateAfter().bci));
+
+            PhiNode returnValuePhi = null;
+            if (hasReturnValue) {
+                returnValuePhi = graph.unique(new PhiNode(invoke.node().kind(), returnMerge));
+            }
+
+            MergeNode exceptionMerge = null;
+            PhiNode exceptionObjectPhi = null;
+            if (invoke instanceof InvokeWithExceptionNode) {
+                InvokeWithExceptionNode invokeWithException = (InvokeWithExceptionNode) invoke;
+                DispatchBeginNode exceptionEdge = invokeWithException.exceptionEdge();
+                ExceptionObjectNode exceptionObject = (ExceptionObjectNode) exceptionEdge.next();
+
+                exceptionMerge = graph.add(new MergeNode());
+                exceptionMerge.setProbability(exceptionEdge.probability());
+
+                FixedNode exceptionSux = exceptionObject.next();
+                graph.addBeforeFixed(exceptionSux, exceptionMerge);
+                exceptionObjectPhi = graph.unique(new PhiNode(Kind.Object, exceptionMerge));
+                exceptionMerge.setStateAfter(exceptionEdge.stateAfter().duplicateModified(invoke.stateAfter().bci, true, Kind.Void, exceptionObjectPhi));
+            }
+
+            // create one separate block for each invoked method
+            BeginNode[] calleeEntryNodes = new BeginNode[numberOfMethods];
+            for (int i = 0; i < numberOfMethods; i++) {
+                int predecessors = 0;
+                double probability = 0;
+                for (int j = 0; j < typesToConcretes.length; j++) {
+                    if (typesToConcretes[j] == i) {
+                        predecessors++;
+                        probability += ptypes[j].probability;
+                    }
+                }
+
+                calleeEntryNodes[i] = createInvocationBlock(graph, invoke, returnMerge, returnValuePhi, exceptionMerge, exceptionObjectPhi, predecessors, invoke.probability() * probability, true);
+            }
+
+            // create the successor for an unknown type
+            FixedNode unknownTypeNode;
+            if (shouldFallbackToInvoke()) {
+                unknownTypeNode = createInvocationBlock(graph, invoke, returnMerge, returnValuePhi, exceptionMerge, exceptionObjectPhi, 1, notRecordedTypeProbability, false);
+            } else {
+                unknownTypeNode = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TypeCheckedInliningViolated, invoke.leafGraphId()));
+            }
+
+            // replace the invoke exception edge
+            if (invoke instanceof InvokeWithExceptionNode) {
+                InvokeWithExceptionNode invokeWithExceptionNode = (InvokeWithExceptionNode) invoke;
+                BeginNode exceptionEdge = invokeWithExceptionNode.exceptionEdge();
+                ExceptionObjectNode exceptionObject = (ExceptionObjectNode) exceptionEdge.next();
+                exceptionObject.replaceAtUsages(exceptionObjectPhi);
+                exceptionObject.setNext(null);
+                GraphUtil.killCFG(invokeWithExceptionNode.exceptionEdge());
+            }
+
+            // replace the invoke with a switch on the type of the actual receiver
+            LoadHubNode receiverHub = graph.add(new LoadHubNode(invoke.methodCallTarget().receiver()));
+            graph.addBeforeFixed(invoke.node(), receiverHub);
+            FixedNode dispatchOnType = createDispatchOnType(graph, receiverHub, calleeEntryNodes, unknownTypeNode);
+
+            assert invoke.next() == continuation;
+            invoke.setNext(null);
+            returnMerge.setNext(continuation);
+            invoke.node().replaceAtUsages(returnValuePhi);
+            invoke.node().replaceAndDelete(dispatchOnType);
+
+            ArrayList<PiNode> replacements = new ArrayList<>();
+
+            // do the actual inlining for every invoke
+            for (int i = 0; i < calleeEntryNodes.length; i++) {
+                BeginNode node = calleeEntryNodes[i];
+                Invoke invokeForInlining = (Invoke) node.next();
+
+                ResolvedJavaType commonType = getLeastCommonType(i);
+                ValueNode receiver = invokeForInlining.methodCallTarget().receiver();
+                boolean exact = getTypeCount(i) == 1;
+                PiNode anchoredReceiver = createAnchoredReceiver(graph, node, commonType, receiver, exact);
+                invokeForInlining.callTarget().replaceFirstInput(receiver, anchoredReceiver);
+
+                ResolvedJavaMethod concrete = concretes.get(i);
+                StructuredGraph calleeGraph = getGraph(concrete, callback);
+                callback.recordMethodContentsAssumption(concrete);
+                assert !IntrinsificationPhase.canIntrinsify(invokeForInlining, concrete, runtime);
+                InliningUtil.inline(invokeForInlining, calleeGraph, false);
+                replacements.add(anchoredReceiver);
+            }
+            if (shouldFallbackToInvoke()) {
+                replacements.add(null);
+            }
+            if (GraalOptions.OptTailDuplication) {
+                /*
+                 * We might want to perform tail duplication at the merge after a type switch, if there are invokes that would
+                 * benefit from the improvement in type information.
+                 */
+                FixedNode current = returnMerge;
+                int opportunities = 0;
+                do {
+                    if (current instanceof InvokeNode && ((InvokeNode) current).methodCallTarget().receiver() == originalReceiver) {
+                        opportunities++;
+                    } else if (current.inputs().contains(originalReceiver)) {
+                        opportunities++;
+                    }
+                    current = ((FixedWithNextNode) current).next();
+                } while (current instanceof FixedWithNextNode);
+                if (opportunities > 0) {
+                    metricInliningTailDuplication.increment();
+                    Debug.log("MultiTypeGuardInlineInfo starting tail duplication (%d opportunities)", opportunities);
+                    TailDuplicationPhase.tailDuplicate(returnMerge, TailDuplicationPhase.TRUE_DECISION, replacements);
+                }
+            }
+        }
+
+        private int getTypeCount(int concreteMethodIndex) {
+            int count = 0;
+            for (int i = 0; i < typesToConcretes.length; i++) {
+                if (typesToConcretes[i] == concreteMethodIndex) {
+                    count++;
+                }
+            }
+            return count;
+        }
+
+        private ResolvedJavaType getLeastCommonType(int concreteMethodIndex) {
+            ResolvedJavaType commonType = null;
+            for (int i = 0; i < typesToConcretes.length; i++) {
+                if (typesToConcretes[i] == concreteMethodIndex) {
+                    if (commonType == null) {
+                        commonType = ptypes[i].type;
+                    } else {
+                        commonType = commonType.leastCommonAncestor(ptypes[i].type);
+                    }
+                }
+            }
+            assert commonType != null;
+            return commonType;
+        }
+
+        private void inlineSingleMethod(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback) {
+            assert concretes.size() == 1 && ptypes.length > 1 && !shouldFallbackToInvoke() && notRecordedTypeProbability == 0;
+
+            MergeNode calleeEntryNode = graph.add(new MergeNode());
+            calleeEntryNode.setProbability(invoke.probability());
+            LoadHubNode receiverHub = graph.add(new LoadHubNode(invoke.methodCallTarget().receiver()));
+            graph.addBeforeFixed(invoke.node(), receiverHub);
+
+            FixedNode unknownTypeNode = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TypeCheckedInliningViolated, invoke.leafGraphId()));
+            FixedNode dispatchOnType = createDispatchOnType(graph, receiverHub, new BeginNode[] {calleeEntryNode}, unknownTypeNode);
+
+            FixedWithNextNode pred = (FixedWithNextNode) invoke.node().predecessor();
+            pred.setNext(dispatchOnType);
+            calleeEntryNode.setNext(invoke.node());
+
+            ResolvedJavaMethod concrete = concretes.get(0);
+            StructuredGraph calleeGraph = getGraph(concrete, callback);
+            assert !IntrinsificationPhase.canIntrinsify(invoke, concrete, runtime);
+            callback.recordMethodContentsAssumption(concrete);
+            InliningUtil.inline(invoke, calleeGraph, false);
+        }
+
+        private FixedNode createDispatchOnType(StructuredGraph graph, LoadHubNode objectClassNode, BeginNode[] calleeEntryNodes, FixedNode unknownTypeSux) {
+            assert ptypes.length > 1;
+
+            ResolvedJavaType[] types = new ResolvedJavaType[ptypes.length];
+            double[] probabilities = new double[ptypes.length + 1];
+            BeginNode[] successors = new BeginNode[ptypes.length + 1];
+            int[] keySuccessors = new int[ptypes.length + 1];
+            for (int i = 0; i < ptypes.length; i++) {
+                types[i] = ptypes[i].type;
+                probabilities[i] = ptypes[i].probability;
+                FixedNode entry = calleeEntryNodes[typesToConcretes[i]];
+                if (entry instanceof MergeNode) {
+                    EndNode endNode = graph.add(new EndNode());
+                    ((MergeNode) entry).addForwardEnd(endNode);
+                    entry = endNode;
+                }
+                successors[i] = BeginNode.begin(entry);
+                keySuccessors[i] = i;
+            }
+            assert !(unknownTypeSux instanceof MergeNode);
+            successors[successors.length - 1] = BeginNode.begin(unknownTypeSux);
+            probabilities[successors.length - 1] = notRecordedTypeProbability;
+            keySuccessors[successors.length - 1] = successors.length - 1;
+
+            TypeSwitchNode typeSwitch = graph.add(new TypeSwitchNode(objectClassNode, successors, probabilities, types, probabilities, keySuccessors));
+
+            return typeSwitch;
+        }
+
+        private static BeginNode createInvocationBlock(StructuredGraph graph, Invoke invoke, MergeNode returnMerge, PhiNode returnValuePhi,
+                        MergeNode exceptionMerge, PhiNode exceptionObjectPhi, int predecessors, double probability, boolean useForInlining) {
+            Invoke duplicatedInvoke = duplicateInvokeForInlining(graph, invoke, exceptionMerge, exceptionObjectPhi, useForInlining, probability);
+            BeginNode calleeEntryNode = graph.add(predecessors > 1 ? new MergeNode() : new BeginNode());
+            calleeEntryNode.setNext(duplicatedInvoke.node());
+            calleeEntryNode.setProbability(probability);
+
+            EndNode endNode = graph.add(new EndNode());
+            endNode.setProbability(probability);
+
+            duplicatedInvoke.setNext(endNode);
+            returnMerge.addForwardEnd(endNode);
+
+            if (returnValuePhi != null) {
+                returnValuePhi.addInput(duplicatedInvoke.node());
+            }
+            return calleeEntryNode;
+        }
+
+        private static Invoke duplicateInvokeForInlining(StructuredGraph graph, Invoke invoke, MergeNode exceptionMerge, PhiNode exceptionObjectPhi, boolean useForInlining, double probability) {
+            Invoke result = (Invoke) invoke.node().copyWithInputs();
+            Node callTarget = result.callTarget().copyWithInputs();
+            result.node().replaceFirstInput(result.callTarget(), callTarget);
+            result.setUseForInlining(useForInlining);
+            result.setProbability(probability);
+
+            Kind kind = invoke.node().kind();
+            if (!kind.isVoid()) {
+                FrameState stateAfter = invoke.stateAfter();
+                stateAfter = stateAfter.duplicate(stateAfter.bci);
+                stateAfter.replaceFirstInput(invoke.node(), result.node());
+                result.setStateAfter(stateAfter);
+            }
+
+            if (invoke instanceof InvokeWithExceptionNode) {
+                assert exceptionMerge != null && exceptionObjectPhi != null;
+
+                InvokeWithExceptionNode invokeWithException = (InvokeWithExceptionNode) invoke;
+                BeginNode exceptionEdge = invokeWithException.exceptionEdge();
+                ExceptionObjectNode exceptionObject = (ExceptionObjectNode) exceptionEdge.next();
+                FrameState stateAfterException = exceptionObject.stateAfter();
+
+                BeginNode newExceptionEdge = (BeginNode) exceptionEdge.copyWithInputs();
+                ExceptionObjectNode newExceptionObject = (ExceptionObjectNode) exceptionObject.copyWithInputs();
+                // set new state (pop old exception object, push new one)
+                newExceptionObject.setStateAfter(stateAfterException.duplicateModified(stateAfterException.bci, stateAfterException.rethrowException(), Kind.Object, newExceptionObject));
+                newExceptionEdge.setNext(newExceptionObject);
+
+                EndNode endNode = graph.add(new EndNode());
+                newExceptionObject.setNext(endNode);
+                exceptionMerge.addForwardEnd(endNode);
+                exceptionObjectPhi.addInput(newExceptionObject);
+
+                ((InvokeWithExceptionNode) result).setExceptionEdge(newExceptionEdge);
+            }
+            return result;
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder builder = new StringBuilder(shouldFallbackToInvoke() ? "megamorphic" : "polymorphic");
+            builder.append(String.format(", %d methods with %d type checks:", concretes.size(), ptypes.length));
+            for (int i = 0; i < concretes.size(); i++) {
+                builder.append(MetaUtil.format("  %H.%n(%p):%r", concretes.get(i)));
+            }
+            return builder.toString();
+        }
+
+        @Override
+        public boolean canDeopt() {
+            return true;
+        }
+    }
+
+
+    /**
+     * Represents an inlining opportunity where the current class hierarchy leads to a monomorphic target method,
+     * but for which an assumption has to be registered because of non-final classes.
+     */
+    private static class AssumptionInlineInfo extends ExactInlineInfo {
+        public final ResolvedJavaType context;
+
+        public AssumptionInlineInfo(Invoke invoke, double weight, int level, ResolvedJavaType context, ResolvedJavaMethod concrete) {
+            super(invoke, weight, level, concrete);
+            this.context = context;
+        }
+
+        @Override
+        public void inline(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback) {
+            if (Debug.isLogEnabled()) {
+                String targetName = MetaUtil.format("%H.%n(%p):%r", invoke.methodCallTarget().targetMethod());
+                String concreteName = MetaUtil.format("%H.%n(%p):%r", concrete);
+                Debug.log("recording concrete method assumption: %s on receiver type %s -> %s", targetName, context, concreteName);
+            }
+            callback.recordConcreteMethodAssumption(invoke.methodCallTarget().targetMethod(), context, concrete);
+
+            super.inline(graph, runtime, callback);
+        }
+
+        @Override
+        public String toString() {
+            return "assumption " + MetaUtil.format("%H.%n(%p):%r", concrete);
+        }
+
+        @Override
+        public boolean canDeopt() {
+            return true;
+        }
+    }
+
+    /**
+     * Determines if inlining is possible at the given invoke node.
+     * @param invoke the invoke that should be inlined
+     * @param level the number of nested inlinings that lead to this invoke, or 0 if the invoke was part of the initial graph
+     * @param runtime a GraalRuntime instance used to determine of the invoke can be inlined and/or should be intrinsified
+     * @param callback a callback that is used to determine the weight of a specific inlining
+     * @return an instance of InlineInfo, or null if no inlining is possible at the given invoke
+     */
+    public static InlineInfo getInlineInfo(Invoke invoke, int level, GraalCodeCacheProvider runtime, Assumptions assumptions, InliningCallback callback, OptimisticOptimizations optimisticOpts) {
+        if (!(invoke.callTarget() instanceof MethodCallTargetNode)) {
+            // The invoke has already been lowered , or has been created as a low-level node. We have no method information.
+            return null;
+        }
+        ResolvedJavaMethod parent = invoke.stateAfter().method();
+        MethodCallTargetNode callTarget = invoke.methodCallTarget();
+        ResolvedJavaMethod targetMethod = callTarget.targetMethod();
+        if (targetMethod == null) {
+            return null;
+        }
+        if (!checkInvokeConditions(invoke)) {
+            return null;
+        }
+
+        if (callTarget.invokeKind() == InvokeKind.Special || targetMethod.canBeStaticallyBound()) {
+            if (checkTargetConditions(invoke, targetMethod, optimisticOpts)) {
+                double weight = callback == null ? 0 : callback.inliningWeight(parent, targetMethod, invoke);
+                return new ExactInlineInfo(invoke, weight, level, targetMethod);
+            }
+            return null;
+        }
+        ObjectStamp receiverStamp = callTarget.receiver().objectStamp();
+        ResolvedJavaType receiverType = receiverStamp.type();
+        if (receiverStamp.isExactType()) {
+            assert receiverType.isSubtypeOf(targetMethod.holder()) : receiverType + " subtype of " + targetMethod.holder() + " for " + targetMethod;
+            ResolvedJavaMethod resolved = receiverType.resolveMethodImpl(targetMethod);
+            if (checkTargetConditions(invoke, resolved, optimisticOpts)) {
+                double weight = callback == null ? 0 : callback.inliningWeight(parent, resolved, invoke);
+                return new ExactInlineInfo(invoke, weight, level, resolved);
+            }
+            return null;
+        }
+        ResolvedJavaType holder = targetMethod.holder();
+
+        if (receiverStamp.type() != null) {
+            // the invoke target might be more specific than the holder (happens after inlining: locals lose their declared type...)
+            // TODO (lstadler) fix this
+            if (receiverType != null && receiverType.isSubtypeOf(holder)) {
+                holder = receiverType;
+            }
+        }
+        // TODO (thomaswue) fix this
+        if (assumptions != null) {
+            ResolvedJavaMethod concrete = holder.uniqueConcreteMethod(targetMethod);
+            if (concrete != null) {
+                if (checkTargetConditions(invoke, concrete, optimisticOpts)) {
+                    double weight = callback == null ? 0 : callback.inliningWeight(parent, concrete, invoke);
+                    return new AssumptionInlineInfo(invoke, weight, level, holder, concrete);
+                }
+                return null;
+            }
+        }
+
+        // type check based inlining
+        return getTypeCheckedInlineInfo(invoke, level, callback, parent, targetMethod, optimisticOpts);
+    }
+
+    private static InlineInfo getTypeCheckedInlineInfo(Invoke invoke, int level, InliningCallback callback, ResolvedJavaMethod parent, ResolvedJavaMethod targetMethod, OptimisticOptimizations optimisticOpts) {
+        ProfilingInfo profilingInfo = parent.profilingInfo();
+        JavaTypeProfile typeProfile = profilingInfo.getTypeProfile(invoke.bci());
+        if (typeProfile != null) {
+            ProfiledType[] ptypes = typeProfile.getTypes();
+
+            if (ptypes != null && ptypes.length > 0) {
+                double notRecordedTypeProbability = typeProfile.getNotRecordedProbability();
+                if (ptypes.length == 1 && notRecordedTypeProbability == 0) {
+                    if (optimisticOpts.inlineMonomorphicCalls()) {
+                        ResolvedJavaType type = ptypes[0].type;
+                        ResolvedJavaMethod concrete = type.resolveMethodImpl(targetMethod);
+                        if (checkTargetConditions(invoke, concrete, optimisticOpts)) {
+                            double weight = callback == null ? 0 : callback.inliningWeight(parent, concrete, invoke);
+                            return new TypeGuardInlineInfo(invoke, weight, level, concrete, type);
+                        }
+
+                        Debug.log("not inlining %s because method can't be inlined", methodName(targetMethod, invoke));
+                        return null;
+                    } else {
+                        Debug.log("not inlining %s because GraalOptions.InlineMonomorphicCalls == false", methodName(targetMethod, invoke));
+                        return null;
+                    }
+                } else {
+                    invoke.setMegamorphic(true);
+                    if (optimisticOpts.inlinePolymorphicCalls() && notRecordedTypeProbability == 0 || optimisticOpts.inlineMegamorphicCalls() && notRecordedTypeProbability > 0) {
+                        // TODO (chaeubl) inlining of multiple methods should work differently
+                        // 1. check which methods can be inlined
+                        // 2. for those methods, use weight and probability to compute which of them should be inlined
+                        // 3. do the inlining
+                        //    a) all seen methods can be inlined -> do so and guard with deopt
+                        //    b) some methods can be inlined -> inline them and fall back to invocation if violated
+                        // TODO (chaeubl) sort types by probability
+
+                        // determine concrete methods and map type to specific method
+                        ArrayList<ResolvedJavaMethod> concreteMethods = new ArrayList<>();
+                        int[] typesToConcretes = new int[ptypes.length];
+                        for (int i = 0; i < ptypes.length; i++) {
+                            ResolvedJavaMethod concrete = ptypes[i].type.resolveMethodImpl(targetMethod);
+
+                            int index = concreteMethods.indexOf(concrete);
+                            if (index < 0) {
+                                index = concreteMethods.size();
+                                concreteMethods.add(concrete);
+                            }
+                            typesToConcretes[i] = index;
+                        }
+
+                        double totalWeight = 0;
+                        boolean canInline = true;
+                        for (ResolvedJavaMethod concrete: concreteMethods) {
+                            if (!checkTargetConditions(invoke, concrete, optimisticOpts)) {
+                                canInline = false;
+                                break;
+                            }
+                            totalWeight += callback == null ? 0 : callback.inliningWeight(parent, concrete, invoke);
+                        }
+
+                        if (canInline) {
+                            return new MultiTypeGuardInlineInfo(invoke, totalWeight, level, concreteMethods, ptypes, typesToConcretes, notRecordedTypeProbability);
+                        } else {
+                            Debug.log("not inlining %s because it is a polymorphic method call and at least one invoked method cannot be inlined", methodName(targetMethod, invoke));
+                            return null;
+                        }
+                    } else {
+                        if (!optimisticOpts.inlinePolymorphicCalls() && notRecordedTypeProbability == 0) {
+                            Debug.log("not inlining %s because GraalOptions.InlinePolymorphicCalls == false", methodName(targetMethod, invoke));
+                        } else {
+                            Debug.log("not inlining %s because GraalOptions.InlineMegamorphicCalls == false", methodName(targetMethod, invoke));
+                        }
+                        return null;
+                    }
+                }
+            }
+
+            Debug.log("not inlining %s because no types/probabilities were recorded", methodName(targetMethod, invoke));
+            return null;
+        } else {
+            Debug.log("not inlining %s because no type profile exists", methodName(targetMethod, invoke));
+            return null;
+        }
+    }
+
+    private static PiNode createAnchoredReceiver(StructuredGraph graph, FixedNode anchor, ResolvedJavaType commonType, ValueNode receiver, boolean exact) {
+        // to avoid that floating reads on receiver fields float above the type check
+        return graph.unique(new PiNode(receiver, anchor, exact ? StampFactory.exactNonNull(commonType) : StampFactory.declaredNonNull(commonType)));
+    }
+
+    private static boolean checkInvokeConditions(Invoke invoke) {
+        if (invoke.stateAfter() == null) {
+            Debug.log("not inlining %s because the invoke has no after state", methodName(invoke.methodCallTarget().targetMethod(), invoke));
+            return false;
+        }
+        if (invoke.predecessor() == null) {
+            Debug.log("not inlining %s because the invoke is dead code", methodName(invoke.methodCallTarget().targetMethod(), invoke));
+            return false;
+        }
+        if (!invoke.useForInlining()) {
+            Debug.log("not inlining %s because invoke is marked to be not used for inlining", methodName(invoke.methodCallTarget().targetMethod(), invoke));
+            return false;
+        }
+        return true;
+    }
+
+    private static boolean checkTargetConditions(Invoke invoke, JavaMethod method, OptimisticOptimizations optimisticOpts) {
+        if (method == null) {
+            Debug.log("not inlining because method is not resolved");
+            return false;
+        }
+        if (!(method instanceof ResolvedJavaMethod)) {
+            Debug.log("not inlining %s because it is unresolved", method.toString());
+            return false;
+        }
+        ResolvedJavaMethod resolvedMethod = (ResolvedJavaMethod) method;
+        if (Modifier.isNative(resolvedMethod.accessFlags())) {
+            Debug.log("not inlining %s because it is a native method", methodName(resolvedMethod, invoke));
+            return false;
+        }
+        if (Modifier.isAbstract(resolvedMethod.accessFlags())) {
+            Debug.log("not inlining %s because it is an abstract method", methodName(resolvedMethod, invoke));
+            return false;
+        }
+        if (!resolvedMethod.holder().isInitialized()) {
+            Debug.log("not inlining %s because of non-initialized class", methodName(resolvedMethod, invoke));
+            return false;
+        }
+        if (!resolvedMethod.canBeInlined()) {
+            Debug.log("not inlining %s because it is marked non-inlinable", methodName(resolvedMethod, invoke));
+            return false;
+        }
+        if (computeRecursiveInliningLevel(invoke.stateAfter(), (ResolvedJavaMethod) method) > GraalOptions.MaximumRecursiveInlining) {
+            Debug.log("not inlining %s because it exceeds the maximum recursive inlining depth", methodName(resolvedMethod, invoke));
+            return false;
+        }
+        OptimisticOptimizations calleeOpts = new OptimisticOptimizations(resolvedMethod);
+        if (calleeOpts.lessOptimisticThan(optimisticOpts)) {
+            Debug.log("not inlining %s because callee uses less optimistic optimizations than caller", methodName(resolvedMethod, invoke));
+            return false;
+        }
+
+        return true;
+    }
+
+    private static int computeRecursiveInliningLevel(FrameState state, ResolvedJavaMethod method) {
+        assert state != null;
+
+        int count = 0;
+        FrameState curState = state;
+        while (curState != null) {
+            if (curState.method() == method) {
+                count++;
+            }
+            curState = curState.outerFrameState();
+        }
+        return count;
+    }
+
+    /**
+     * Performs an actual inlining, thereby replacing the given invoke with the given inlineGraph.
+     *
+     * @param invoke the invoke that will be replaced
+     * @param inlineGraph the graph that the invoke will be replaced with
+     * @param receiverNullCheck true if a null check needs to be generated for non-static inlinings, false if no such check is required
+     */
+    public static void inline(Invoke invoke, StructuredGraph inlineGraph, boolean receiverNullCheck) {
+        InliningIdentifier identifier = new InliningIdentifier(inlineGraph.method(), invoke);
+        NodeInputList<ValueNode> parameters = invoke.callTarget().arguments();
+        StructuredGraph graph = (StructuredGraph) invoke.node().graph();
+
+        FrameState stateAfter = invoke.stateAfter();
+        assert stateAfter.isAlive();
+
+        IdentityHashMap<Node, Node> replacements = new IdentityHashMap<>();
+        ArrayList<Node> nodes = new ArrayList<>();
+        ReturnNode returnNode = null;
+        UnwindNode unwindNode = null;
+        StartNode entryPointNode = inlineGraph.start();
+        FixedNode firstCFGNode = entryPointNode.next();
+        for (Node node : inlineGraph.getNodes()) {
+            if (node == entryPointNode || node == entryPointNode.stateAfter()) {
+                // Do nothing.
+            } else if (node instanceof LocalNode) {
+                replacements.put(node, parameters.get(((LocalNode) node).index()));
+            } else {
+                nodes.add(node);
+                if (node instanceof ReturnNode) {
+                    assert returnNode == null;
+                    returnNode = (ReturnNode) node;
+                } else if (node instanceof UnwindNode) {
+                    assert unwindNode == null;
+                    unwindNode = (UnwindNode) node;
+                }
+            }
+        }
+        replacements.put(entryPointNode, BeginNode.prevBegin(invoke.node())); // ensure proper anchoring of things that where anchored to the StartNode
+
+        assert invoke.node().successors().first() != null : invoke;
+        assert invoke.node().predecessor() != null;
+
+        Map<Node, Node> duplicates = graph.addDuplicates(nodes, replacements);
+        FixedNode firstCFGNodeDuplicate = (FixedNode) duplicates.get(firstCFGNode);
+        if (receiverNullCheck) {
+            receiverNullCheck(invoke);
+        }
+        invoke.node().replaceAtPredecessor(firstCFGNodeDuplicate);
+
+        FrameState stateAtExceptionEdge = null;
+        if (invoke instanceof InvokeWithExceptionNode) {
+            InvokeWithExceptionNode invokeWithException = ((InvokeWithExceptionNode) invoke);
+            if (unwindNode != null) {
+                assert unwindNode.predecessor() != null;
+                assert invokeWithException.exceptionEdge().successors().count() == 1;
+                ExceptionObjectNode obj = (ExceptionObjectNode) invokeWithException.exceptionEdge().next();
+                stateAtExceptionEdge = obj.stateAfter();
+                UnwindNode unwindDuplicate = (UnwindNode) duplicates.get(unwindNode);
+                obj.replaceAtUsages(unwindDuplicate.exception());
+                unwindDuplicate.clearInputs();
+                Node n = obj.next();
+                obj.setNext(null);
+                unwindDuplicate.replaceAndDelete(n);
+            } else {
+                invokeWithException.killExceptionEdge();
+            }
+        } else {
+            if (unwindNode != null) {
+                UnwindNode unwindDuplicate = (UnwindNode) duplicates.get(unwindNode);
+                DeoptimizeNode deoptimizeNode = new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler, invoke.leafGraphId());
+                unwindDuplicate.replaceAndDelete(graph.add(deoptimizeNode));
+                // move the deopt upwards if there is a monitor exit that tries to use the "after exception" frame state
+                // (because there is no "after exception" frame state!)
+                if (deoptimizeNode.predecessor() instanceof MonitorExitNode) {
+                    MonitorExitNode monitorExit = (MonitorExitNode) deoptimizeNode.predecessor();
+                    if (monitorExit.stateAfter() != null && monitorExit.stateAfter().bci == FrameState.AFTER_EXCEPTION_BCI) {
+                        FrameState monitorFrameState = monitorExit.stateAfter();
+                        graph.removeFixed(monitorExit);
+                        monitorFrameState.safeDelete();
+                    }
+                }
+            }
+        }
+
+        FrameState outerFrameState = null;
+        double invokeProbability = invoke.node().probability();
+        for (Node node : duplicates.values()) {
+            if (GraalOptions.ProbabilityAnalysis) {
+                if (node instanceof FixedNode) {
+                    FixedNode fixed = (FixedNode) node;
+                    double newProbability = fixed.probability() * invokeProbability;
+                    if (GraalOptions.LimitInlinedProbability) {
+                        newProbability = Math.min(newProbability, invokeProbability);
+                    }
+                    fixed.setProbability(newProbability);
+                }
+            }
+            if (node instanceof FrameState) {
+                FrameState frameState = (FrameState) node;
+                assert frameState.bci != FrameState.BEFORE_BCI;
+                if (frameState.bci == FrameState.AFTER_BCI) {
+                    frameState.replaceAndDelete(stateAfter);
+                } else if (frameState.bci == FrameState.AFTER_EXCEPTION_BCI) {
+                    if (frameState.isAlive()) {
+                        assert stateAtExceptionEdge != null;
+                        frameState.replaceAndDelete(stateAtExceptionEdge);
+                    } else {
+                        assert stateAtExceptionEdge == null;
+                    }
+                } else {
+                    // only handle the outermost frame states
+                    if (frameState.outerFrameState() == null) {
+                        assert frameState.method() == inlineGraph.method();
+                        if (outerFrameState == null) {
+                            outerFrameState = stateAfter.duplicateModified(invoke.bci(), stateAfter.rethrowException(), invoke.node().kind());
+                            outerFrameState.setDuringCall(true);
+                        }
+                        frameState.setOuterFrameState(outerFrameState);
+                        frameState.setInliningIdentifier(identifier);
+                    }
+                }
+            }
+        }
+
+        Node returnValue = null;
+        if (returnNode != null) {
+            if (returnNode.result() instanceof LocalNode) {
+                returnValue = replacements.get(returnNode.result());
+            } else {
+                returnValue = duplicates.get(returnNode.result());
+            }
+            invoke.node().replaceAtUsages(returnValue);
+            Node returnDuplicate = duplicates.get(returnNode);
+            returnDuplicate.clearInputs();
+            Node n = invoke.next();
+            invoke.setNext(null);
+            returnDuplicate.replaceAndDelete(n);
+        }
+
+        invoke.node().clearInputs();
+        invoke.node().replaceAtUsages(null);
+        GraphUtil.killCFG(invoke.node());
+
+        if (stateAfter.usages().isEmpty()) {
+            stateAfter.safeDelete();
+        }
+    }
+
+    public static void receiverNullCheck(Invoke invoke) {
+        MethodCallTargetNode callTarget = invoke.methodCallTarget();
+        StructuredGraph graph = (StructuredGraph) invoke.graph();
+        NodeInputList<ValueNode> parameters = callTarget.arguments();
+        ValueNode firstParam = parameters.size() <= 0 ? null : parameters.get(0);
+        if (!callTarget.isStatic() && firstParam.kind() == Kind.Object && !firstParam.objectStamp().nonNull()) {
+            graph.addBeforeFixed(invoke.node(), graph.add(new FixedGuardNode(graph.unique(new IsNullNode(firstParam)), DeoptimizationReason.ClassCastException, DeoptimizationAction.InvalidateReprofile, true, invoke.leafGraphId())));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/IntList.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.phases.util;
+
+import java.util.*;
+
+/**
+ * An expandable and indexable list of {@code int}s.
+ *
+ * This class avoids the boxing/unboxing incurred by {@code ArrayList<Integer>}.
+ */
+public final class IntList {
+
+    private int[] array;
+    private int size;
+
+    /**
+     * Creates an int list with a specified initial capacity.
+     *
+     * @param initialCapacity
+     */
+    public IntList(int initialCapacity) {
+        array = new int[initialCapacity];
+    }
+
+    /**
+     * Creates an int list with a specified initial array.
+     *
+     * @param array the initial array used for the list (no copy is made)
+     * @param initialSize the initial {@linkplain #size() size} of the list (must be less than or equal to {@code array.length}
+     */
+    public IntList(int[] array, int initialSize) {
+        assert initialSize <= array.length;
+        this.array = array;
+        this.size = initialSize;
+    }
+
+    /**
+     * Makes a new int list by copying a range from a given int list.
+     *
+     * @param other the list from which a range of values is to be copied into the new list
+     * @param startIndex the index in {@code other} at which to start copying
+     * @param length the number of values to copy from {@code other}
+     * @return a new int list whose {@linkplain #size() size} and capacity is {@code length}
+     */
+    public static IntList copy(IntList other, int startIndex, int length) {
+        return copy(other, startIndex, length, length);
+    }
+
+    /**
+     * Makes a new int list by copying a range from a given int list.
+     *
+     * @param other the list from which a range of values is to be copied into the new list
+     * @param startIndex the index in {@code other} at which to start copying
+     * @param length the number of values to copy from {@code other}
+     * @param initialCapacity the initial capacity of the new int list (must be greater or equal to {@code length})
+     * @return a new int list whose {@linkplain #size() size} is {@code length}
+     */
+    public static IntList copy(IntList other, int startIndex, int length, int initialCapacity) {
+        assert initialCapacity >= length : "initialCapacity < length";
+        int[] array = new int[initialCapacity];
+        System.arraycopy(other.array, startIndex, array, 0, length);
+        return new IntList(array, length);
+    }
+
+    public int size() {
+        return size;
+    }
+
+    /**
+     * Appends a value to the end of this list, increasing its {@linkplain #size() size} by 1.
+     *
+     * @param value the value to append
+     */
+    public void add(int value) {
+        if (size == array.length) {
+            int newSize = (size * 3) / 2 + 1;
+            array = Arrays.copyOf(array, newSize);
+        }
+        array[size++] = value;
+    }
+
+    /**
+     * Gets the value in this list at a given index.
+     *
+     * @param index the index of the element to return
+     * @throws IndexOutOfBoundsException if {@code index < 0 || index >= size()}
+     */
+    public int get(int index) {
+        if (index >= size) {
+            throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
+        }
+        return array[index];
+    }
+
+    /**
+     * Sets the size of this list to 0.
+     */
+    public void clear() {
+        size = 0;
+    }
+
+    /**
+     * Sets a value at a given index in this list.
+     *
+     * @param index the index of the element to update
+     * @param value the new value of the element
+     * @throws IndexOutOfBoundsException if {@code index < 0 || index >= size()}
+     */
+    public void set(int index, int value) {
+        if (index >= size) {
+            throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
+        }
+        array[index] = value;
+    }
+
+    /**
+     * Adjusts the {@linkplain #size() size} of this int list.
+     *
+     * If {@code newSize < size()}, the size is changed to {@code newSize}.
+     * If {@code newSize > size()}, sufficient 0 elements are {@linkplain #add(int) added}
+     * until {@code size() == newSize}.
+     *
+     * @param newSize the new size of this int list
+     */
+    public void setSize(int newSize) {
+        if (newSize < size) {
+            size = newSize;
+        } else if (newSize > size) {
+            array = Arrays.copyOf(array, newSize);
+        }
+    }
+
+    @Override
+    public String toString() {
+        if (array.length == size) {
+            return Arrays.toString(array);
+        }
+        return Arrays.toString(Arrays.copyOf(array, size));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/Util.java	Sun Oct 07 14:15:44 2012 +0200
@@ -0,0 +1,342 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.phases.util;
+
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+
+/**
+ * The {@code Util} class contains a motley collection of utility methods used throughout the compiler.
+ */
+public class Util {
+
+    public static final int PRINTING_LINE_WIDTH = 40;
+    public static final char SECTION_CHARACTER = '*';
+    public static final char SUB_SECTION_CHARACTER = '=';
+    public static final char SEPERATOR_CHARACTER = '-';
+
+    public static <T> boolean replaceInList(T a, T b, List<T> list) {
+        final int max = list.size();
+        for (int i = 0; i < max; i++) {
+            if (list.get(i) == a) {
+                list.set(i, b);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Statically cast an object to an arbitrary Object type. Dynamically checked.
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T uncheckedCast(@SuppressWarnings("unused") Class<T> type, Object object) {
+        return (T) object;
+    }
+
+    /**
+     * Statically cast an object to an arbitrary Object type. Dynamically checked.
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T uncheckedCast(Object object) {
+        return (T) object;
+    }
+
+    /**
+     * Utility method to combine a base hash with the identity hash of one or more objects.
+     *
+     * @param hash the base hash
+     * @param x the object to add to the hash
+     * @return the combined hash
+     */
+    public static int hash1(int hash, Object x) {
+        // always set at least one bit in case the hash wraps to zero
+        return 0x10000000 | (hash + 7 * System.identityHashCode(x));
+    }
+
+    /**
+     * Utility method to combine a base hash with the identity hash of one or more objects.
+     *
+     * @param hash the base hash
+     * @param x the first object to add to the hash
+     * @param y the second object to add to the hash
+     * @return the combined hash
+     */
+    public static int hash2(int hash, Object x, Object y) {
+        // always set at least one bit in case the hash wraps to zero
+        return 0x20000000 | (hash + 7 * System.identityHashCode(x) + 11 * System.identityHashCode(y));
+    }
+
+    /**
+     * Utility method to combine a base hash with the identity hash of one or more objects.
+     *
+     * @param hash the base hash
+     * @param x the first object to add to the hash
+     * @param y the second object to add to the hash
+     * @param z the third object to add to the hash
+     * @return the combined hash
+     */
+    public static int hash3(int hash, Object x, Object y, Object z) {
+        // always set at least one bit in case the hash wraps to zero
+        return 0x30000000 | (hash + 7 * System.identityHashCode(x) + 11 * System.identityHashCode(y) + 13 * System.identityHashCode(z));
+    }
+
+    /**
+     * Utility method to combine a base hash with the identity hash of one or more objects.
+     *
+     * @param hash the base hash
+     * @param x the first object to add to the hash
+     * @param y the second object to add to the hash
+     * @param z the third object to add to the hash
+     * @param w the fourth object to add to the hash
+     * @return the combined hash
+     */
+    public static int hash4(int hash, Object x, Object y, Object z, Object w) {
+        // always set at least one bit in case the hash wraps to zero
+        return 0x40000000 | (hash + 7 * System.identityHashCode(x) + 11 * System.identityHashCode(y) + 13 * System.identityHashCode(z) + 17 * System.identityHashCode(w));
+    }
+
+    static {
+        assert CodeUtil.log2(2) == 1;
+        assert CodeUtil.log2(4) == 2;
+        assert CodeUtil.log2(8) == 3;
+        assert CodeUtil.log2(16) == 4;
+        assert CodeUtil.log2(32) == 5;
+        assert CodeUtil.log2(0x40000000) == 30;
+
+        assert CodeUtil.log2(2L) == 1;
+        assert CodeUtil.log2(4L) == 2;
+        assert CodeUtil.log2(8L) == 3;
+        assert CodeUtil.log2(16L) == 4;
+        assert CodeUtil.log2(32L) == 5;
+        assert CodeUtil.log2(0x4000000000000000L) == 62;
+
+        assert !CodeUtil.isPowerOf2(3);
+        assert !CodeUtil.isPowerOf2(5);
+        assert !CodeUtil.isPowerOf2(7);
+        assert !CodeUtil.isPowerOf2(-1);
+
+        assert CodeUtil.isPowerOf2(2);
+        assert CodeUtil.isPowerOf2(4);
+        assert CodeUtil.isPowerOf2(8);
+        assert CodeUtil.isPowerOf2(16);
+        assert CodeUtil.isPowerOf2(32);
+        assert CodeUtil.isPowerOf2(64);
+    }
+
+    /**
+     * Sets the element at a given position of a list and ensures that this position exists. If the list is current
+     * shorter than the position, intermediate positions are filled with a given value.
+     *
+     * @param list the list to put the element into
+     * @param pos the position at which to insert the element
+     * @param x the element that should be inserted
+     * @param filler the filler element that is used for the intermediate positions in case the list is shorter than pos
+     */
+    public static <T> void atPutGrow(List<T> list, int pos, T x, T filler) {
+        if (list.size() < pos + 1) {
+            while (list.size() < pos + 1) {
+                list.add(filler);
+            }
+            assert list.size() == pos + 1;
+        }
+
+        assert list.size() >= pos + 1;
+        list.set(pos, x);
+    }
+
+    public static void breakpoint() {
+        // do nothing.
+    }
+
+    public static void guarantee(boolean b, String string) {
+        if (!b) {
+            throw new BailoutException(string);
+        }
+    }
+
+    public static void warning(String string) {
+        TTY.println("WARNING: " + string);
+    }
+
+    public static int safeToInt(long l) {
+        assert (int) l == l;
+        return (int) l;
+    }
+
+    public static int roundUp(int number, int mod) {
+        return ((number + mod - 1) / mod) * mod;
+    }
+
+    public static void printSection(String name, char sectionCharacter) {
+
+        String header = " " + name + " ";
+        int remainingCharacters = PRINTING_LINE_WIDTH - header.length();
+        int leftPart = remainingCharacters / 2;
+        int rightPart = remainingCharacters - leftPart;
+        for (int i = 0; i < leftPart; i++) {
+            TTY.print(sectionCharacter);
+        }
+
+        TTY.print(header);
+
+        for (int i = 0; i < rightPart; i++) {
+            TTY.print(sectionCharacter);
+        }
+
+        TTY.println();
+    }
+
+    /**
+     * Prints entries in a byte array as space separated hex values to {@link TTY}.
+     *
+     * @param address an address at which the bytes are located. This is used to print an address prefix per line of output.
+     * @param array the array containing all the bytes to print
+     * @param bytesPerLine the number of values to print per line of output
+     */
+    public static void printBytes(long address, byte[] array, int bytesPerLine) {
+        printBytes(address, array, 0, array.length, bytesPerLine);
+    }
+
+    /**
+     * Prints entries in a byte array as space separated hex values to {@link TTY}.
+     *
+     * @param address an address at which the bytes are located. This is used to print an address prefix per line of output.
+     * @param array the array containing the bytes to print
+     * @param offset the offset in {@code array} of the values to print
+     * @param length the number of values from {@code array} print
+     * @param bytesPerLine the number of values to print per line of output
+     */
+    public static void printBytes(long address, byte[] array, int offset, int length, int bytesPerLine) {
+        assert bytesPerLine > 0;
+        boolean newLine = true;
+        for (int i = 0; i < length; i++) {
+            if (newLine) {
+                TTY.print("%08x: ", address + i);
+                newLine = false;
+            }
+            TTY.print("%02x ", array[i]);
+            if (i % bytesPerLine == bytesPerLine - 1) {
+                TTY.println();
+                newLine = true;
+            }
+        }
+
+        if (length % bytesPerLine != bytesPerLine) {
+            TTY.println();
+        }
+    }
+
+    public static boolean isShiftCount(int x) {
+        return 0 <= x && x < 32;
+    }
+
+    /**
+     * Determines if a given {@code int} value is the range of unsigned byte values.
+     */
+    public static boolean isUByte(int x) {
+        return (x & 0xff) == x;
+    }
+
+    /**
+     * Determines if a given {@code int} value is the range of signed byte values.
+     */
+    public static boolean isByte(int x) {
+        return (byte) x == x;
+    }
+
+    /**
+     * Determines if a given {@code long} value is the range of unsigned byte values.
+     */
+    public static boolean isUByte(long x) {
+        return (x & 0xffL) == x;
+    }
+
+    /**
+     * Determines if a given {@code long} value is the range of signed byte values.
+     */
+    public static boolean isByte(long l) {
+        return (byte) l == l;
+    }
+
+    /**
+     * Determines if a given {@code long} value is the range of unsigned int values.
+     */
+    public static boolean isUInt(long x) {
+        return (x & 0xffffffffL) == x;
+    }
+
+    /**
+     * Determines if a given {@code long} value is the range of signed int values.
+     */
+    public static boolean isInt(long l) {
+        return (int) l == l;
+    }
+    /**
+     * Determines if a given {@code int} value is the range of signed short values.
+     */
+    public static boolean isShort(int x) {
+        return (short) x == x;
+    }
+
+    public static boolean is32bit(long x) {
+        return -0x80000000L <= x && x < 0x80000000L;
+    }
+
+    public static short safeToShort(int v) {
+        assert isShort(v);
+        return (short) v;
+    }
+
+    public static boolean isFixed(Node n) {
+        return n instanceof FixedNode;
+    }
+
+    public static boolean isFloating(Node n) {
+        return n instanceof FloatingNode;
+    }
+
+    /**
+     * Creates an array of integers of length "size", in which each number from 0 to (size - 1) occurs exactly once. The
+     * integers are sorted using the given comparator. This can be used to create a sorting for arrays that cannot be
+     * modified directly.
+     *
+     * @param size The size of the range to be sorted.
+     * @param comparator A comparator that is used to compare indexes.
+     * @return An array of integers that contains each number from 0 to (size - 1) exactly once, sorted using the
+     *         comparator.
+     */
+    public static Integer[] createSortedPermutation(int size, Comparator<Integer> comparator) {
+        Integer[] indexes = new Integer[size];
+        for (int i = 0; i < size; i++) {
+            indexes[i] = i;
+        }
+        Arrays.sort(indexes, comparator);
+        return indexes;
+    }
+}
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java	Sun Oct 07 14:15:44 2012 +0200
@@ -29,12 +29,12 @@
 import java.util.Map.Entry;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.schedule.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.NodeClass.NodeClassIterator;
 import com.oracle.graal.graph.NodeClass.Position;
 import com.oracle.graal.lir.cfg.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.schedule.*;
 
 public class BinaryGraphPrinter implements GraphPrinter{
     private static final int CONSTANT_POOL_MAX_SIZE = 2000;
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java	Sun Oct 07 14:15:44 2012 +0200
@@ -37,6 +37,7 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.cfg.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.*;
 
 /**
  * Observes compilation events and uses {@link CFGPrinter} to produce a control flow graph for the <a
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinter.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinter.java	Sun Oct 07 14:15:44 2012 +0200
@@ -25,8 +25,8 @@
 import java.io.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.schedule.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.phases.schedule.*;
 
 interface GraphPrinter extends Closeable {
     /**
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java	Sun Oct 07 14:15:44 2012 +0200
@@ -30,9 +30,9 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.phases.*;
 
 /**
  * Observes compilation events and uses {@link IdealGraphPrinter} to generate a graph representation that can be
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java	Sun Oct 07 14:15:44 2012 +0200
@@ -27,7 +27,6 @@
 import java.util.Map.Entry;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.schedule.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.Verbosity;
 import com.oracle.graal.graph.NodeClass.NodeClassIterator;
@@ -35,6 +34,7 @@
 import com.oracle.graal.java.*;
 import com.oracle.graal.lir.cfg.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.schedule.*;
 
 /**
  * Generates a representation of {@link Graph Graphs} that can be visualized and inspected with the <a
--- a/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/InstanceOfTest.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/InstanceOfTest.java	Sun Oct 07 14:15:44 2012 +0200
@@ -27,9 +27,9 @@
 import org.junit.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.phases.phases.*;
 import com.oracle.graal.snippets.CheckCastTest.*;
 
 /**
--- a/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/InvokeTest.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/InvokeTest.java	Sun Oct 07 14:15:44 2012 +0200
@@ -25,9 +25,9 @@
 import org.junit.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.compiler.test.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.phases.*;
 
 /**
  * Tests the implementation of the snippets for lowering the INVOKE* instructions.
--- a/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/WordTest.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/WordTest.java	Sun Oct 07 14:15:44 2012 +0200
@@ -32,6 +32,7 @@
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.test.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.*;
 import com.oracle.graal.snippets.Snippet.InliningPolicy;
 
 /**
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/GraalIntrinsics.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/GraalIntrinsics.java	Sun Oct 07 14:15:44 2012 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.snippets;
 
-import com.oracle.graal.compiler.*;
+import com.oracle.graal.phases.*;
 
 /**
  * Definition of the snippets that are VM-independent and can be intrinsified by Graal in any VM.
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java	Sun Oct 07 14:15:44 2012 +0200
@@ -28,9 +28,6 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.phases.*;
-import com.oracle.graal.compiler.util.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
@@ -38,6 +35,9 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.phases.*;
+import com.oracle.graal.phases.util.*;
 import com.oracle.graal.snippets.Snippet.InliningPolicy;
 
 /**
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationPhase.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationPhase.java	Sun Oct 07 14:15:44 2012 +0200
@@ -26,7 +26,6 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.ConstantNodeParameter;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
@@ -35,6 +34,7 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.phases.phases.*;
 import com.oracle.graal.snippets.Snippet.Fold;
 
 public class SnippetIntrinsificationPhase extends Phase {
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java	Sun Oct 07 14:15:44 2012 +0200
@@ -29,7 +29,6 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.loop.*;
@@ -39,6 +38,7 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.phases.phases.*;
 import com.oracle.graal.snippets.Snippet.ConstantParameter;
 import com.oracle.graal.snippets.Snippet.Parameter;
 import com.oracle.graal.snippets.Snippet.Varargs;
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetVerificationPhase.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetVerificationPhase.java	Sun Oct 07 14:15:44 2012 +0200
@@ -27,13 +27,13 @@
 import java.lang.reflect.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.phases.phases.*;
 import com.oracle.graal.snippets.Word.*;
 
 /**
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java	Sun Oct 07 14:15:44 2012 +0200
@@ -23,7 +23,6 @@
 package com.oracle.graal.snippets;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.PhiNode.PhiType;
@@ -33,6 +32,7 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.phases.phases.*;
 import com.oracle.graal.snippets.Word.Opcode;
 import com.oracle.graal.snippets.Word.Operation;
 
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java	Sun Oct 07 14:15:44 2012 +0200
@@ -27,9 +27,6 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.JavaType.*;
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.phases.*;
-import com.oracle.graal.compiler.schedule.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.cfg.*;
@@ -41,6 +38,9 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.virtual.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.phases.*;
+import com.oracle.graal.phases.schedule.*;
 import com.oracle.graal.virtual.nodes.*;
 
 class EscapeAnalysisIteration {
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/experimental/SplitPartialEscapeAnalysisPhase.java	Sun Oct 07 14:11:55 2012 +0200
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/experimental/SplitPartialEscapeAnalysisPhase.java	Sun Oct 07 14:15:44 2012 +0200
@@ -27,9 +27,6 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.JavaType.Representation;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.*;
-import com.oracle.graal.compiler.phases.*;
-import com.oracle.graal.compiler.schedule.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.cfg.*;
@@ -41,6 +38,9 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.virtual.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.phases.*;
+import com.oracle.graal.phases.schedule.*;
 import com.oracle.graal.virtual.nodes.*;
 import com.oracle.graal.virtual.phases.ea.*;
 import com.oracle.graal.virtual.phases.ea.experimental.EffectList.*;