changeset 19944:f73a6e260e0c

Merge
author Tom Rodriguez <tom.rodriguez@oracle.com>
date Wed, 18 Mar 2015 10:07:47 -0700
parents 6a0692faf9fd (current diff) ed3e144ced29 (diff)
children efa840053649 b3a2e8e564ad
files graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARCScratchRegister.java
diffstat 24 files changed, 192 insertions(+), 815 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java	Wed Mar 18 10:01:25 2015 -0700
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCMacroAssembler.java	Wed Mar 18 10:07:47 2015 -0700
@@ -39,6 +39,9 @@
      * patched.
      */
     private static final SPARCAddress Placeholder = new SPARCAddress(g0, 0);
+    private final ScratchRegister[] scratchRegister = new ScratchRegister[]{new ScratchRegister(g1), new ScratchRegister(g3)};
+    // Points to the next free scratch register
+    private int nextFreeScratchRegister = 0;
 
     public SPARCMacroAssembler(TargetDescription target, RegisterConfig registerConfig) {
         super(target, registerConfig);
@@ -389,4 +392,26 @@
     public void signx(Register rd) {
         sra(rd, g0, rd);
     }
+
+    public ScratchRegister getScratchRegister() {
+        return scratchRegister[nextFreeScratchRegister++];
+    }
+
+    public class ScratchRegister implements AutoCloseable {
+        private final Register register;
+
+        public ScratchRegister(Register register) {
+            super();
+            this.register = register;
+        }
+
+        public Register getRegister() {
+            return register;
+        }
+
+        public void close() {
+            assert nextFreeScratchRegister > 0 : "Close called too often";
+            nextFreeScratchRegister--;
+        }
+    }
 }
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java	Wed Mar 18 10:01:25 2015 -0700
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java	Wed Mar 18 10:07:47 2015 -0700
@@ -298,9 +298,6 @@
     public static final OptionValue<Boolean> OptFloatingReads = new OptionValue<>(true);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Boolean> OptTailDuplication = new OptionValue<>(false);
-
-    @Option(help = "", type = OptionType.Debug)
     public static final OptionValue<Boolean> OptEliminatePartiallyRedundantGuards = new OptionValue<>(true);
 
     @Option(help = "", type = OptionType.Debug)
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/FloatStamp.java	Wed Mar 18 10:01:25 2015 -0700
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/FloatStamp.java	Wed Mar 18 10:07:47 2015 -0700
@@ -47,6 +47,7 @@
     public FloatStamp(int bits, double lowerBound, double upperBound, boolean nonNaN) {
         super(bits, OPS);
         assert bits == 64 || (bits == 32 && (Double.isNaN(lowerBound) || (float) lowerBound == lowerBound) && (Double.isNaN(upperBound) || (float) upperBound == upperBound));
+        assert Double.isNaN(lowerBound) == Double.isNaN(upperBound);
         this.lowerBound = lowerBound;
         this.upperBound = upperBound;
         this.nonNaN = nonNaN;
@@ -130,6 +131,10 @@
         return nonNaN;
     }
 
+    public boolean isNaN() {
+        return Double.isNaN(lowerBound);
+    }
+
     public boolean isUnrestricted() {
         return lowerBound == Double.NEGATIVE_INFINITY && upperBound == Double.POSITIVE_INFINITY && !nonNaN;
     }
@@ -629,6 +634,9 @@
         @Override
         public Stamp foldStamp(Stamp s) {
             FloatStamp stamp = (FloatStamp) s;
+            if (stamp.isNaN()) {
+                return stamp;
+            }
             return new FloatStamp(stamp.getBits(), 0, Math.max(-stamp.lowerBound(), stamp.upperBound()), stamp.isNonNaN());
         }
     },
@@ -666,8 +674,19 @@
 
         @Override
         public Stamp foldStamp(Stamp stamp) {
-            assert stamp instanceof FloatStamp && ((FloatStamp) stamp).getBits() == 32;
-            return StampFactory.forKind(Kind.Int);
+            FloatStamp floatStamp = (FloatStamp) stamp;
+            assert floatStamp.getBits() == 32;
+            boolean mustHaveZero = !floatStamp.isNonNaN();
+            int lowerBound = (int) floatStamp.lowerBound();
+            int upperBound = (int) floatStamp.upperBound();
+            if (mustHaveZero) {
+                if (lowerBound > 0) {
+                    lowerBound = 0;
+                } else if (upperBound < 0) {
+                    upperBound = 0;
+                }
+            }
+            return StampFactory.forInteger(Kind.Int, lowerBound, upperBound);
         }
     },
 
@@ -681,8 +700,19 @@
 
         @Override
         public Stamp foldStamp(Stamp stamp) {
-            assert stamp instanceof FloatStamp && ((FloatStamp) stamp).getBits() == 32;
-            return StampFactory.forKind(Kind.Long);
+            FloatStamp floatStamp = (FloatStamp) stamp;
+            assert floatStamp.getBits() == 32;
+            boolean mustHaveZero = !floatStamp.isNonNaN();
+            long lowerBound = (long) floatStamp.lowerBound();
+            long upperBound = (long) floatStamp.upperBound();
+            if (mustHaveZero) {
+                if (lowerBound > 0) {
+                    lowerBound = 0;
+                } else if (upperBound < 0) {
+                    upperBound = 0;
+                }
+            }
+            return StampFactory.forInteger(Kind.Long, lowerBound, upperBound);
         }
     },
 
@@ -696,8 +726,19 @@
 
         @Override
         public Stamp foldStamp(Stamp stamp) {
-            assert stamp instanceof FloatStamp && ((FloatStamp) stamp).getBits() == 64;
-            return StampFactory.forKind(Kind.Int);
+            FloatStamp floatStamp = (FloatStamp) stamp;
+            assert floatStamp.getBits() == 64;
+            boolean mustHaveZero = !floatStamp.isNonNaN();
+            int lowerBound = (int) floatStamp.lowerBound();
+            int upperBound = (int) floatStamp.upperBound();
+            if (mustHaveZero) {
+                if (lowerBound > 0) {
+                    lowerBound = 0;
+                } else if (upperBound < 0) {
+                    upperBound = 0;
+                }
+            }
+            return StampFactory.forInteger(Kind.Int, lowerBound, upperBound);
         }
     },
 
@@ -711,8 +752,19 @@
 
         @Override
         public Stamp foldStamp(Stamp stamp) {
-            assert stamp instanceof FloatStamp && ((FloatStamp) stamp).getBits() == 64;
-            return StampFactory.forKind(Kind.Long);
+            FloatStamp floatStamp = (FloatStamp) stamp;
+            assert floatStamp.getBits() == 64;
+            boolean mustHaveZero = !floatStamp.isNonNaN();
+            long lowerBound = (long) floatStamp.lowerBound();
+            long upperBound = (long) floatStamp.upperBound();
+            if (mustHaveZero) {
+                if (lowerBound > 0) {
+                    lowerBound = 0;
+                } else if (upperBound < 0) {
+                    upperBound = 0;
+                }
+            }
+            return StampFactory.forInteger(Kind.Long, lowerBound, upperBound);
         }
     },
 
@@ -726,8 +778,9 @@
 
         @Override
         public Stamp foldStamp(Stamp stamp) {
-            assert stamp instanceof FloatStamp && ((FloatStamp) stamp).getBits() == 32;
-            return StampFactory.forKind(Kind.Double);
+            FloatStamp floatStamp = (FloatStamp) stamp;
+            assert floatStamp.getBits() == 32;
+            return StampFactory.forFloat(Kind.Double, floatStamp.lowerBound(), floatStamp.upperBound(), floatStamp.isNonNaN());
         }
     },
 
@@ -741,8 +794,9 @@
 
         @Override
         public Stamp foldStamp(Stamp stamp) {
-            assert stamp instanceof FloatStamp && ((FloatStamp) stamp).getBits() == 64;
-            return StampFactory.forKind(Kind.Float);
+            FloatStamp floatStamp = (FloatStamp) stamp;
+            assert floatStamp.getBits() == 64;
+            return StampFactory.forFloat(Kind.Float, (float) floatStamp.lowerBound(), (float) floatStamp.upperBound(), floatStamp.isNonNaN());
         }
     });
 }
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java	Wed Mar 18 10:01:25 2015 -0700
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java	Wed Mar 18 10:07:47 2015 -0700
@@ -973,7 +973,9 @@
         public Stamp foldStamp(Stamp input) {
             IntegerStamp stamp = (IntegerStamp) input;
             assert stamp.getBits() == 32;
-            return StampFactory.forKind(Kind.Float);
+            float lowerBound = stamp.lowerBound();
+            float upperBound = stamp.upperBound();
+            return StampFactory.forFloat(Kind.Float, lowerBound, upperBound, true);
         }
     },
 
@@ -989,7 +991,9 @@
         public Stamp foldStamp(Stamp input) {
             IntegerStamp stamp = (IntegerStamp) input;
             assert stamp.getBits() == 64;
-            return StampFactory.forKind(Kind.Float);
+            float lowerBound = stamp.lowerBound();
+            float upperBound = stamp.upperBound();
+            return StampFactory.forFloat(Kind.Float, lowerBound, upperBound, true);
         }
     },
 
@@ -1005,7 +1009,9 @@
         public Stamp foldStamp(Stamp input) {
             IntegerStamp stamp = (IntegerStamp) input;
             assert stamp.getBits() == 32;
-            return StampFactory.forKind(Kind.Double);
+            double lowerBound = stamp.lowerBound();
+            double upperBound = stamp.upperBound();
+            return StampFactory.forFloat(Kind.Double, lowerBound, upperBound, true);
         }
     },
 
@@ -1021,7 +1027,9 @@
         public Stamp foldStamp(Stamp input) {
             IntegerStamp stamp = (IntegerStamp) input;
             assert stamp.getBits() == 64;
-            return StampFactory.forKind(Kind.Double);
+            double lowerBound = stamp.lowerBound();
+            double upperBound = stamp.upperBound();
+            return StampFactory.forFloat(Kind.Double, lowerBound, upperBound, true);
         }
     });
 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java	Wed Mar 18 10:01:25 2015 -0700
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java	Wed Mar 18 10:07:47 2015 -0700
@@ -75,10 +75,6 @@
             appendPhase(new LoopFullUnrollPhase(canonicalizer));
         }
 
-        if (OptTailDuplication.getValue()) {
-            appendPhase(new TailDuplicationPhase(canonicalizer));
-        }
-
         if (PartialEscapeAnalysis.getValue()) {
             appendPhase(new PartialEscapePhase(true, canonicalizer));
         }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java	Wed Mar 18 10:01:25 2015 -0700
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java	Wed Mar 18 10:07:47 2015 -0700
@@ -40,6 +40,8 @@
 @ServiceProvider(HotSpotBackendFactory.class)
 public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory {
 
+    private static final int PLUGIN_COUNT_ESTIMATE = 160;
+
     protected Architecture createArchitecture(HotSpotVMConfig config) {
         return new AMD64(computeFeatures(config), computeFlags(config));
     }
@@ -171,7 +173,8 @@
                 wordTypes = new HotSpotWordTypes(metaAccess, target.wordKind);
             }
             try (InitTimer rt = timer("create GraphBuilderPhase plugins")) {
-                plugins = HotSpotGraphBuilderPlugins.create(runtime.getConfig(), wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider, replacements, target.arch);
+                plugins = HotSpotGraphBuilderPlugins.create(runtime.getConfig(), wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider, replacements, target.arch,
+                                PLUGIN_COUNT_ESTIMATE);
                 replacements.setGraphBuilderPlugins(plugins);
             }
             try (InitTimer rt = timer("create Suites provider")) {
@@ -260,15 +263,15 @@
         } else {
             /*
              * System V Application Binary Interface, AMD64 Architecture Processor Supplement
-             * 
+             *
              * Draft Version 0.96
-             * 
+             *
              * http://www.uclibc.org/docs/psABI-x86_64.pdf
-             * 
+             *
              * 3.2.1
-             * 
+             *
              * ...
-             * 
+             *
              * This subsection discusses usage of each register. Registers %rbp, %rbx and %r12
              * through %r15 "belong" to the calling function and the called function is required to
              * preserve their values. In other words, a called function must preserve these
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Wed Mar 18 10:01:25 2015 -0700
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Wed Mar 18 10:07:47 2015 -0700
@@ -38,6 +38,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.ScratchRegister;
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setx;
 import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.hotspot.*;
@@ -52,7 +53,6 @@
 import com.oracle.graal.lir.sparc.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.sparc.*;
 
 /**
  * HotSpot SPARC specific backend.
@@ -113,7 +113,7 @@
                     if (SPARCAssembler.isSimm13(address.getDisplacement())) {
                         masm.stx(g0, address);
                     } else {
-                        try (SPARCScratchRegister sc = SPARCScratchRegister.get()) {
+                        try (ScratchRegister sc = masm.getScratchRegister()) {
                             Register scratch = sc.getRegister();
                             new Setx(address.getDisplacement(), scratch).emit(masm);
                             masm.stx(g0, new SPARCAddress(sp, scratch));
@@ -148,7 +148,7 @@
             if (SPARCAssembler.isSimm13(stackpoinerChange)) {
                 masm.save(sp, stackpoinerChange, sp);
             } else {
-                try (SPARCScratchRegister sc = SPARCScratchRegister.get()) {
+                try (ScratchRegister sc = masm.getScratchRegister()) {
                     Register scratch = sc.getRegister();
                     new Setx(stackpoinerChange, scratch).emit(masm);
                     masm.save(sp, scratch, sp);
@@ -227,7 +227,7 @@
                 CallingConvention cc = regConfig.getCallingConvention(JavaCall, null, new JavaType[]{getProviders().getMetaAccess().lookupJavaType(Object.class)}, getTarget(), false);
                 Register inlineCacheKlass = g5; // see MacroAssembler::ic_call
 
-                try (SPARCScratchRegister sc = SPARCScratchRegister.get()) {
+                try (ScratchRegister sc = masm.getScratchRegister()) {
                     Register scratch = sc.getRegister();
                     Register receiver = asRegister(cc.getArgument(0));
                     SPARCAddress src = new SPARCAddress(receiver, config.hubOffset);
@@ -261,7 +261,7 @@
 
         if (unverifiedStub != null) {
             masm.bind(unverifiedStub);
-            try (SPARCScratchRegister sc = SPARCScratchRegister.get()) {
+            try (ScratchRegister sc = masm.getScratchRegister()) {
                 Register scratch = sc.getRegister();
                 SPARCCall.indirectJmp(crb, masm, scratch, foreignCalls.lookupForeignCall(IC_MISS_HANDLER));
             }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java	Wed Mar 18 10:01:25 2015 -0700
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java	Wed Mar 18 10:07:47 2015 -0700
@@ -39,6 +39,8 @@
 @ServiceProvider(HotSpotBackendFactory.class)
 public class SPARCHotSpotBackendFactory implements HotSpotBackendFactory {
 
+    private static final int PLUGIN_COUNT_ESTIMATE = 155;
+
     protected Architecture createArchitecture(HotSpotVMConfig config) {
         return new SPARC(computeFeatures(config));
     }
@@ -68,7 +70,8 @@
         HotSpotReplacementsImpl replacements = new HotSpotReplacementsImpl(p, snippetReflection, runtime.getConfig(), target);
         HotSpotDisassemblerProvider disassembler = new HotSpotDisassemblerProvider(runtime);
         HotSpotWordTypes wordTypes = new HotSpotWordTypes(metaAccess, target.wordKind);
-        Plugins plugins = HotSpotGraphBuilderPlugins.create(runtime.getConfig(), wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider, replacements, target.arch);
+        Plugins plugins = HotSpotGraphBuilderPlugins.create(runtime.getConfig(), wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider, replacements, target.arch,
+                        PLUGIN_COUNT_ESTIMATE);
         replacements.setGraphBuilderPlugins(plugins);
         HotSpotSuitesProvider suites = createSuites(runtime, plugins);
         HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers, snippetReflection,
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCounterOp.java	Wed Mar 18 10:01:25 2015 -0700
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCounterOp.java	Wed Mar 18 10:07:47 2015 -0700
@@ -27,6 +27,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.lir.*;
@@ -36,19 +37,12 @@
 public class SPARCHotSpotCounterOp extends HotSpotCounterOp {
     public static final LIRInstructionClass<SPARCHotSpotCounterOp> TYPE = LIRInstructionClass.create(SPARCHotSpotCounterOp.class);
 
-    @Temp({OperandFlag.REG}) private AllocatableValue scratch0;
-    @Temp({OperandFlag.REG}) private AllocatableValue scratch1;
-
-    public SPARCHotSpotCounterOp(String name, String group, Value increment, HotSpotRegistersProvider registers, HotSpotVMConfig config, AllocatableValue scratch0, AllocatableValue scratch1) {
+    public SPARCHotSpotCounterOp(String name, String group, Value increment, HotSpotRegistersProvider registers, HotSpotVMConfig config) {
         super(TYPE, name, group, increment, registers, config);
-        this.scratch0 = scratch0;
-        this.scratch1 = scratch1;
     }
 
-    public SPARCHotSpotCounterOp(String[] names, String[] groups, Value[] increments, HotSpotRegistersProvider registers, HotSpotVMConfig config, AllocatableValue scratch0, AllocatableValue scratch1) {
+    public SPARCHotSpotCounterOp(String[] names, String[] groups, Value[] increments, HotSpotRegistersProvider registers, HotSpotVMConfig config) {
         super(TYPE, names, groups, increments, registers, config);
-        this.scratch0 = scratch0;
-        this.scratch1 = scratch1;
     }
 
     @Override
@@ -58,27 +52,32 @@
 
         // address for counters array
         SPARCAddress countersArrayAddr = new SPARCAddress(thread, config.graalCountersThreadOffset);
-        Register countersArrayReg = asRegister(scratch0);
+        try (ScratchRegister scratch = masm.getScratchRegister()) {
+            Register countersArrayReg = scratch.getRegister();
 
-        // load counters array
-        masm.ldx(countersArrayAddr, countersArrayReg);
+            // load counters array
+            masm.ldx(countersArrayAddr, countersArrayReg);
 
-        forEachCounter((name, group, increment) -> emitIncrement(masm, target, countersArrayReg, name, group, increment));
+            forEachCounter((name, group, increment) -> emitIncrement(masm, target, countersArrayReg, name, group, increment));
+        }
     }
 
     private void emitIncrement(SPARCMacroAssembler masm, TargetDescription target, Register countersArrayReg, String name, String group, Value increment) {
         // address for counter
         SPARCAddress counterAddr = new SPARCAddress(countersArrayReg, getDisplacementForLongIndex(target, getIndex(name, group, increment)));
-        Register counterReg = asRegister(scratch1);
-        // load counter value
-        masm.ldx(counterAddr, counterReg);
-        // increment counter
-        if (isConstant(increment)) {
-            masm.add(counterReg, asInt(asConstant(increment)), counterReg);
-        } else {
-            masm.add(counterReg, asRegister(increment), counterReg);
+
+        try (ScratchRegister scratch = masm.getScratchRegister()) {
+            Register counterReg = scratch.getRegister();
+            // load counter value
+            masm.ldx(counterAddr, counterReg);
+            // increment counter
+            if (isConstant(increment)) {
+                masm.add(counterReg, asInt(asConstant(increment)), counterReg);
+            } else {
+                masm.add(counterReg, asRegister(increment), counterReg);
+            }
+            // store counter value
+            masm.stx(counterReg, counterAddr);
         }
-        // store counter value
-        masm.stx(counterReg, counterAddr);
     }
 }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotDeoptimizeCallerOp.java	Wed Mar 18 10:01:25 2015 -0700
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotDeoptimizeCallerOp.java	Wed Mar 18 10:07:47 2015 -0700
@@ -26,10 +26,10 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.ScratchRegister;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.sparc.*;
-import com.oracle.graal.sparc.*;
 
 /**
  * Removes the current frame and tail calls the uncommon trap routine.
@@ -52,7 +52,7 @@
         // HotSpotFrameContext frameContext = backend.new HotSpotFrameContext(isStub);
         // frameContext.enter(crb);
 
-        try (SPARCScratchRegister sc = SPARCScratchRegister.get()) {
+        try (ScratchRegister sc = masm.getScratchRegister()) {
             Register scratch = sc.getRegister();
             SPARCCall.indirectJmp(crb, masm, scratch, crb.foreignCalls.lookupForeignCall(UNCOMMON_TRAP_HANDLER));
         }
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotJumpToExceptionHandlerInCallerOp.java	Wed Mar 18 10:01:25 2015 -0700
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotJumpToExceptionHandlerInCallerOp.java	Wed Mar 18 10:07:47 2015 -0700
@@ -31,9 +31,9 @@
 import com.oracle.graal.asm.sparc.*;
 import com.oracle.graal.asm.sparc.SPARCAssembler.CC;
 import com.oracle.graal.asm.sparc.SPARCAssembler.ConditionFlag;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.ScratchRegister;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.sparc.*;
 
 /**
  * Sets up the arguments for an exception handler in the callers frame, removes the current frame
@@ -69,7 +69,7 @@
 
         // Restore SP from L7 if the exception PC is a method handle call site.
         SPARCAddress dst = new SPARCAddress(thread, isMethodHandleReturnOffset);
-        try (SPARCScratchRegister scratch = SPARCScratchRegister.get()) {
+        try (ScratchRegister scratch = masm.getScratchRegister()) {
             Register scratchReg = scratch.getRegister();
             masm.lduw(dst, scratchReg);
             masm.cmp(scratchReg, scratchReg);
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Wed Mar 18 10:01:25 2015 -0700
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Wed Mar 18 10:07:47 2015 -0700
@@ -49,7 +49,6 @@
 import com.oracle.graal.lir.sparc.SPARCMove.NullCheckOp;
 import com.oracle.graal.lir.sparc.SPARCMove.StoreConstantOp;
 import com.oracle.graal.lir.sparc.SPARCMove.StoreOp;
-import com.oracle.graal.sparc.*;
 
 public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSpotLIRGenerator {
 
@@ -368,28 +367,18 @@
     @Override
     public LIRInstruction createBenchmarkCounter(String name, String group, Value increment) {
         if (BenchmarkCounters.enabled) {
-            try (SPARCScratchRegister sc0 = SPARCScratchRegister.get()) {
-                RegisterValue scratch0 = sc0.getRegister().asValue(getLIRKindTool().getWordKind());
-                try (SPARCScratchRegister sc1 = SPARCScratchRegister.get()) {
-                    RegisterValue scratch1 = sc1.getRegister().asValue(getLIRKindTool().getWordKind());
-                    return new SPARCHotSpotCounterOp(name, group, increment, getProviders().getRegisters(), config, scratch0, scratch1);
-                }
-            }
+            return new SPARCHotSpotCounterOp(name, group, increment, getProviders().getRegisters(), config);
+        } else {
+            return null;
         }
-        return null;
     }
 
     @Override
     public LIRInstruction createMultiBenchmarkCounter(String[] names, String[] groups, Value[] increments) {
         if (BenchmarkCounters.enabled) {
-            try (SPARCScratchRegister sc0 = SPARCScratchRegister.get()) {
-                RegisterValue scratch0 = sc0.getRegister().asValue(getLIRKindTool().getWordKind());
-                try (SPARCScratchRegister sc1 = SPARCScratchRegister.get()) {
-                    RegisterValue scratch1 = sc1.getRegister().asValue(getLIRKindTool().getWordKind());
-                    return new SPARCHotSpotCounterOp(names, groups, increments, getProviders().getRegisters(), config, scratch0, scratch1);
-                }
-            }
+            return new SPARCHotSpotCounterOp(names, groups, increments, getProviders().getRegisters(), config);
+        } else {
+            return null;
         }
-        return null;
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java	Wed Mar 18 10:01:25 2015 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java	Wed Mar 18 10:07:47 2015 -0700
@@ -85,6 +85,8 @@
                        "  dacapo = 'err, starting =====, PASSED in'%n" +
                        "  specjvm2008 = 'out,Iteration ~ (~s) begins:,Iteration ~ (~s) ends:'", type = OptionType.Debug)
         private static final OptionValue<String> BenchmarkDynamicCounters = new OptionValue<>(null);
+        @Option(help = "Use grouping separators for number printing", type = OptionType.Debug)
+        private static final OptionValue<Boolean> DynamicCountersPrintGroupSeparator = new OptionValue<>(true);
         //@formatter:on
     }
 
@@ -207,28 +209,29 @@
                 cnt--;
             }
 
+            String numFmt = Options.DynamicCountersPrintGroupSeparator.getValue() ? "%,19d" : "%19d";
             if (staticCounter) {
                 out.println("=========== " + group + " (static counters):");
                 for (Map.Entry<Long, String> entry : sorted.entrySet()) {
                     long counter = entry.getKey() / array.length;
-                    out.format(Locale.US, "%,19d %3d%%  %s\n", counter, percentage(counter, sum), entry.getValue());
+                    out.format(Locale.US, numFmt + " %3d%%  %s\n", counter, percentage(counter, sum), entry.getValue());
                 }
-                out.format(Locale.US, "%,19d total\n", sum);
+                out.format(Locale.US, numFmt + " total\n", sum);
             } else {
                 if (group.startsWith("~")) {
                     out.println("=========== " + group + " (dynamic counters), time = " + seconds + " s:");
                     for (Map.Entry<Long, String> entry : sorted.entrySet()) {
                         long counter = entry.getKey() / array.length;
-                        out.format(Locale.US, "%,19d/s %3d%%  %s\n", (long) (counter / seconds), percentage(counter, sum), entry.getValue());
+                        out.format(Locale.US, numFmt + "/s %3d%%  %s\n", (long) (counter / seconds), percentage(counter, sum), entry.getValue());
                     }
-                    out.format(Locale.US, "%,19d/s total\n", (long) (sum / seconds));
+                    out.format(Locale.US, numFmt + "/s total\n", (long) (sum / seconds));
                 } else {
                     out.println("=========== " + group + " (dynamic counters):");
                     for (Map.Entry<Long, String> entry : sorted.entrySet()) {
                         long counter = entry.getKey() / array.length;
-                        out.format(Locale.US, "%,19d %3d%%  %s\n", counter, percentage(counter, sum), entry.getValue());
+                        out.format(Locale.US, numFmt + " %3d%%  %s\n", counter, percentage(counter, sum), entry.getValue());
                     }
-                    out.format(Locale.US, "%,19d total\n", sum);
+                    out.format(Locale.US, numFmt + " total\n", sum);
                 }
             }
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java	Wed Mar 18 10:01:25 2015 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java	Wed Mar 18 10:07:47 2015 -0700
@@ -109,15 +109,15 @@
         } else if (n instanceof CheckCastDynamicNode) {
             checkcastDynamicSnippets.lower((CheckCastDynamicNode) n, tool);
         } else if (n instanceof InstanceOfNode) {
-            if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) {
+            if (graph.getGuardsStage().areDeoptsFixed()) {
                 instanceofSnippets.lower((InstanceOfNode) n, tool);
             }
         } else if (n instanceof InstanceOfDynamicNode) {
-            if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) {
+            if (graph.getGuardsStage().areDeoptsFixed()) {
                 instanceofSnippets.lower((InstanceOfDynamicNode) n, tool);
             }
         } else if (n instanceof ClassIsAssignableFromNode) {
-            if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) {
+            if (graph.getGuardsStage().areDeoptsFixed()) {
                 instanceofSnippets.lower((ClassIsAssignableFromNode) n, tool);
             }
         } else if (n instanceof NewInstanceNode) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java	Wed Mar 18 10:01:25 2015 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java	Wed Mar 18 10:07:47 2015 -0700
@@ -49,8 +49,6 @@
  */
 public class HotSpotGraphBuilderPlugins {
 
-    private static final int PLUGIN_COUNT_ESTIMATE = 160;
-
     /**
      * Creates a {@link Plugins} object that should be used when running on HotSpot.
      *
@@ -60,9 +58,9 @@
      * @param stampProvider
      */
     public static Plugins create(HotSpotVMConfig config, HotSpotWordTypes wordTypes, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection,
-                    SnippetReflectionProvider snippetReflection, ForeignCallsProvider foreignCalls, StampProvider stampProvider, ReplacementsImpl replacements, Architecture arch) {
-
-        InvocationPlugins invocationPlugins = new HotSpotInvocationPlugins(config, metaAccess, PLUGIN_COUNT_ESTIMATE);
+                    SnippetReflectionProvider snippetReflection, ForeignCallsProvider foreignCalls, StampProvider stampProvider, ReplacementsImpl replacements, Architecture arch,
+                    int pluginCountEstimate) {
+        InvocationPlugins invocationPlugins = new HotSpotInvocationPlugins(config, metaAccess, pluginCountEstimate);
 
         Plugins plugins = new Plugins(invocationPlugins);
         NodeIntrinsificationPhase nodeIntrinsification = new NodeIntrinsificationPhase(metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider);
@@ -81,8 +79,8 @@
         StandardGraphBuilderPlugins.registerInvocationPlugins(metaAccess, arch, invocationPlugins, !config.useHeapProfiler);
 
         int size = invocationPlugins.size();
-        assert PLUGIN_COUNT_ESTIMATE >= size : String.format("adjust %s.PLUGIN_COUNT_ESTIMATE to be above or equal to %d", HotSpotGraphBuilderPlugins.class.getSimpleName(), size);
-        assert PLUGIN_COUNT_ESTIMATE - size < 20 : String.format("adjust %s.PLUGIN_COUNT_ESTIMATE to be closer to %d", HotSpotGraphBuilderPlugins.class.getSimpleName(), size);
+        assert pluginCountEstimate >= size : String.format("adjust %s.PLUGIN_COUNT_ESTIMATE to be above or equal to %d", HotSpotGraphBuilderPlugins.class.getSimpleName(), size);
+        assert pluginCountEstimate - size < 20 : String.format("adjust %s.PLUGIN_COUNT_ESTIMATE to be closer to %d", HotSpotGraphBuilderPlugins.class.getSimpleName(), size);
         return plugins;
     }
 
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Wed Mar 18 10:01:25 2015 -0700
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCArithmetic.java	Wed Mar 18 10:07:47 2015 -0700
@@ -37,7 +37,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.sparc.*;
-import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setx;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
@@ -371,7 +371,7 @@
                 masm.mulx(asIntReg(src1), asIntReg(src2), asIntReg(dst));
                 break;
             case IMULCC:
-                try (SPARCScratchRegister tmpScratch = SPARCScratchRegister.get()) {
+                try (ScratchRegister tmpScratch = masm.getScratchRegister()) {
                     Register tmp = tmpScratch.getRegister();
                     masm.mulx(asIntReg(src1), asIntReg(src2), asIntReg(dst));
                     Label noOverflow = new Label();
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Wed Mar 18 10:01:25 2015 -0700
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Wed Mar 18 10:07:47 2015 -0700
@@ -39,6 +39,7 @@
 import com.oracle.graal.asm.sparc.SPARCAssembler.BranchPredict;
 import com.oracle.graal.asm.sparc.SPARCAssembler.CC;
 import com.oracle.graal.asm.sparc.SPARCAssembler.ConditionFlag;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.ScratchRegister;
 import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setx;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.calc.*;
@@ -47,7 +48,6 @@
 import com.oracle.graal.lir.SwitchStrategy.BaseSwitchClosure;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.sparc.SPARC.CPUFeature;
-import com.oracle.graal.sparc.*;
 
 public class SPARCControlFlow {
 
@@ -219,21 +219,14 @@
                 actualConditionFlag = actualConditionFlag.mirror();
             }
             boolean isValidConstant = isConstant(actualY) && isSimm5(asConstant(actualY));
-            SPARCScratchRegister scratch = null;
-            try {
+            try (ScratchRegister scratch = masm.getScratchRegister()) {
                 if (isConstant(actualY) && !isValidConstant) { // Make sure, the y value is loaded
-                    scratch = SPARCScratchRegister.get();
                     Value scratchValue = scratch.getRegister().asValue(actualY.getLIRKind());
                     SPARCMove.move(crb, masm, scratchValue, actualY, SPARCDelayedControlTransfer.DUMMY);
                     actualY = scratchValue;
                 }
                 emitCBCond(masm, actualX, actualY, actualTrueTarget, actualConditionFlag);
                 masm.nop();
-            } finally {
-                if (scratch != null) {
-                    // release the scratch if used
-                    scratch.close();
-                }
             }
             if (needJump) {
                 masm.jmp(actualFalseTarget);
@@ -481,14 +474,14 @@
             if (isSimm13(lowKey)) {
                 masm.sub(value, lowKey, scratchReg);
             } else {
-                try (SPARCScratchRegister sc = SPARCScratchRegister.get()) {
+                try (ScratchRegister sc = masm.getScratchRegister()) {
                     Register scratch2 = sc.getRegister();
                     new Setx(lowKey, scratch2).emit(masm);
                     masm.sub(value, scratch2, scratchReg);
                 }
             }
             int upperLimit = highKey - lowKey;
-            try (SPARCScratchRegister sc = SPARCScratchRegister.get()) {
+            try (ScratchRegister sc = masm.getScratchRegister()) {
                 Register scratch2 = sc.getRegister();
                 if (isSimm13(upperLimit)) {
                     masm.cmp(scratchReg, upperLimit);
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Wed Mar 18 10:01:25 2015 -0700
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java	Wed Mar 18 10:07:47 2015 -0700
@@ -31,7 +31,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.sparc.*;
-import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setx;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.ImplicitNullCheck;
@@ -133,7 +133,7 @@
             Kind inputKind = (Kind) input.getPlatformKind();
             Kind resultKind = (Kind) result.getPlatformKind();
             int resultKindSize = crb.target.getSizeInBytes(resultKind);
-            try (SPARCScratchRegister sc = SPARCScratchRegister.get()) {
+            try (ScratchRegister sc = masm.getScratchRegister()) {
                 Register scratch = sc.getRegister();
                 SPARCAddress tempAddress = generateSimm13OffsetLoad((SPARCAddress) crb.asAddress(temp), masm, scratch);
                 switch (inputKind) {
@@ -295,7 +295,7 @@
 
         @Override
         public void emitMemAccess(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
-            try (SPARCScratchRegister sc = SPARCScratchRegister.get()) {
+            try (ScratchRegister sc = masm.getScratchRegister()) {
                 Register scratch = sc.getRegister();
                 final SPARCAddress addr = generateSimm13OffsetLoad(address.toAddress(), masm, scratch);
                 final Register dst = asRegister(result);
@@ -495,7 +495,7 @@
         @Override
         public void emitMemAccess(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
             assert isRegister(input);
-            try (SPARCScratchRegister sc = SPARCScratchRegister.get()) {
+            try (ScratchRegister sc = masm.getScratchRegister()) {
                 Register scratch = sc.getRegister();
                 SPARCAddress addr = generateSimm13OffsetLoad(address.toAddress(), masm, scratch);
                 delayedControlTransfer.emitControlTransfer(crb, masm);
@@ -548,7 +548,7 @@
 
         @Override
         public void emitMemAccess(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
-            try (SPARCScratchRegister sc = SPARCScratchRegister.get()) {
+            try (ScratchRegister sc = masm.getScratchRegister()) {
                 Register scratch = sc.getRegister();
                 SPARCAddress addr = generateSimm13OffsetLoad(address.toAddress(), masm, scratch);
                 delayedControlTransfer.emitControlTransfer(crb, masm);
@@ -604,7 +604,7 @@
                 if (constant.isDefaultForKind() || constant.isNull()) {
                     reg2stack(crb, masm, result, g0.asValue(LIRKind.derive(input)), delaySlotLir);
                 } else {
-                    try (SPARCScratchRegister sc = SPARCScratchRegister.get()) {
+                    try (ScratchRegister sc = masm.getScratchRegister()) {
                         Register scratch = sc.getRegister();
                         long value = constant.asLong();
                         if (isSimm13(value)) {
@@ -681,7 +681,7 @@
 
     private static void reg2stack(CompilationResultBuilder crb, SPARCMacroAssembler masm, Value result, Value input, SPARCDelayedControlTransfer delaySlotLir) {
         SPARCAddress dst = (SPARCAddress) crb.asAddress(result);
-        try (SPARCScratchRegister sc = SPARCScratchRegister.get()) {
+        try (ScratchRegister sc = masm.getScratchRegister()) {
             Register scratch = sc.getRegister();
             dst = generateSimm13OffsetLoad(dst, masm, scratch);
             Register src = asRegister(input);
@@ -716,7 +716,7 @@
 
     private static void stack2reg(CompilationResultBuilder crb, SPARCMacroAssembler masm, Value result, Value input, SPARCDelayedControlTransfer delaySlotLir) {
         SPARCAddress src = (SPARCAddress) crb.asAddress(input);
-        try (SPARCScratchRegister sc = SPARCScratchRegister.get()) {
+        try (ScratchRegister sc = masm.getScratchRegister()) {
             Register scratch = sc.getRegister();
             src = generateSimm13OffsetLoad(src, masm, scratch);
             Register dst = asRegister(result);
@@ -752,7 +752,7 @@
     }
 
     private static void const2reg(CompilationResultBuilder crb, SPARCMacroAssembler masm, Value result, JavaConstant input, SPARCDelayedControlTransfer delaySlotLir) {
-        try (SPARCScratchRegister sc = SPARCScratchRegister.get()) {
+        try (ScratchRegister sc = masm.getScratchRegister()) {
             Register scratch = sc.getRegister();
             boolean hasVIS3 = ((SPARC) masm.target.arch).getFeatures().contains(CPUFeature.VIS3);
             switch (input.getKind().getStackKind()) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Wed Mar 18 10:01:25 2015 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Wed Mar 18 10:07:47 2015 -0700
@@ -79,6 +79,10 @@
         public boolean areFrameStatesAtSideEffects() {
             return !this.areFrameStatesAtDeopts();
         }
+
+        public boolean areDeoptsFixed() {
+            return this.ordinal() >= FIXED_DEOPTS.ordinal();
+        }
     }
 
     /**
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Wed Mar 18 10:01:25 2015 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Wed Mar 18 10:07:47 2015 -0700
@@ -260,7 +260,7 @@
                         canonical = ((BinaryCommutative<?>) node).maybeCommuteInputs();
                     }
                 } catch (Throwable e) {
-                    throw Debug.handle(e);
+                    throw new RuntimeException(e);
                 }
                 if (performReplacement(node, canonical)) {
                     return true;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Wed Mar 18 10:01:25 2015 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,575 +0,0 @@
-/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.phases.common;
-
-import static com.oracle.graal.compiler.common.GraalOptions.*;
-
-import java.util.*;
-import java.util.function.*;
-
-import com.oracle.graal.compiler.common.*;
-import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.Graph.DuplicationReplacement;
-import com.oracle.graal.graph.Graph.Mark;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodeinfo.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.VirtualState.NodeClosure;
-import com.oracle.graal.nodes.debug.*;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.util.*;
-import com.oracle.graal.nodes.virtual.*;
-import com.oracle.graal.phases.*;
-import com.oracle.graal.phases.graph.*;
-import com.oracle.graal.phases.tiers.*;
-
-/**
- * This class is a phase that looks for opportunities for tail duplication. The static method
- * {@link #tailDuplicate(AbstractMergeNode, TailDuplicationDecision, List, PhaseContext, CanonicalizerPhase)}
- * can also be used to drive tail duplication from other places, e.g., inlining.
- */
-public class TailDuplicationPhase extends BasePhase<PhaseContext> {
-
-    /*
-     * Various metrics on the circumstances in which tail duplication was/wasn't performed.
-     */
-    private static final DebugMetric metricDuplicationConsidered = Debug.metric("DuplicationConsidered");
-    private static final DebugMetric metricDuplicationPerformed = Debug.metric("DuplicationPerformed");
-
-    private final CanonicalizerPhase canonicalizer;
-
-    @NodeInfo(allowedUsageTypes = {InputType.Guard, InputType.Anchor})
-    static final class DummyAnchorNode extends FixedWithNextNode implements GuardingNode, AnchoringNode {
-        public static final NodeClass<DummyAnchorNode> TYPE = NodeClass.create(DummyAnchorNode.class);
-
-        public DummyAnchorNode() {
-            super(TYPE, StampFactory.forVoid());
-        }
-
-    }
-
-    /**
-     * 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(AbstractMergeNode 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(AbstractMergeNode merge, int fixedNodeCount) {
-            if (fixedNodeCount < TailDuplicationTrivialSize.getValue()) {
-                return true;
-            }
-            ArrayList<PhiNode> improvements = null;
-            for (PhiNode phi : merge.phis()) {
-                Stamp phiStamp = phi.stamp();
-                for (ValueNode input : phi.values()) {
-                    if (!input.stamp().equals(phiStamp)) {
-                        if (improvements == null) {
-                            improvements = new ArrayList<>();
-                        }
-                        if (!improvements.contains(phi)) {
-                            improvements.add(phi);
-                        }
-                        break;
-                    }
-                }
-            }
-            if (improvements == null) {
-                return false;
-            }
-            FixedNode current = merge;
-            int opportunities = 0;
-            while (current instanceof FixedWithNextNode) {
-                current = ((FixedWithNextNode) current).next();
-                if (current instanceof VirtualizableAllocation) {
-                    return false;
-                }
-                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(AbstractMergeNode merge, int fixedNodeCount) {
-            return true;
-        }
-    };
-
-    public TailDuplicationPhase(CanonicalizerPhase canonicalizer) {
-        this.canonicalizer = canonicalizer;
-    }
-
-    @Override
-    protected void run(StructuredGraph graph, PhaseContext phaseContext) {
-        if (graph.hasNode(AbstractMergeNode.TYPE)) {
-            ToDoubleFunction<FixedNode> nodeProbabilities = new FixedNodeProbabilityCache();
-
-            // A snapshot is taken here, so that new MergeNode instances aren't considered for tail
-            // duplication.
-            for (AbstractMergeNode merge : graph.getNodes(AbstractMergeNode.TYPE).snapshot()) {
-                if (!(merge instanceof LoopBeginNode) && nodeProbabilities.applyAsDouble(merge) >= TailDuplicationProbability.getValue()) {
-                    tailDuplicate(merge, DEFAULT_DECISION, null, phaseContext, canonicalizer);
-                }
-            }
-        }
-    }
-
-    /**
-     * 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 AbstractMergeNode#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.
-     * @param phaseContext
-     */
-    public static boolean tailDuplicate(AbstractMergeNode merge, TailDuplicationDecision decision, List<GuardedValueNode> replacements, PhaseContext phaseContext, CanonicalizerPhase canonicalizer) {
-        assert !(merge instanceof LoopBeginNode);
-        assert replacements == null || replacements.size() == merge.forwardEndCount();
-        FixedNode fixed = merge;
-        int fixedCount = 0;
-        while (fixed instanceof FixedWithNextNode) {
-            fixed = ((FixedWithNextNode) fixed).next();
-            if (fixed instanceof CommitAllocationNode || fixed instanceof ControlFlowAnchorNode) {
-                return false;
-            }
-            fixedCount++;
-        }
-        if (fixedCount > 1) {
-            metricDuplicationConsidered.increment();
-            if (decision.doTransform(merge, fixedCount)) {
-                metricDuplicationPerformed.increment();
-                new DuplicationOperation(merge, replacements, canonicalizer).duplicate(phaseContext);
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * This class encapsulates one tail duplication operation on a specific
-     * {@link AbstractMergeNode}.
-     */
-    private static class DuplicationOperation {
-
-        private final AbstractMergeNode merge;
-        private final StructuredGraph graph;
-
-        private final Map<ValueNode, PhiNode> bottomPhis = Node.newMap();
-        private final List<GuardedValueNode> replacements;
-
-        private final CanonicalizerPhase canonicalizer;
-
-        /**
-         * 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(AbstractMergeNode merge, List<GuardedValueNode> replacements, CanonicalizerPhase canonicalizer) {
-            this.merge = merge;
-            this.replacements = replacements;
-            this.graph = merge.graph();
-            this.canonicalizer = canonicalizer;
-        }
-
-        /**
-         * 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>
-         *
-         * @param phaseContext
-         */
-        private void duplicate(PhaseContext phaseContext) {
-            Debug.log("tail duplication at merge %s in %s", merge, graph.method());
-
-            Mark startMark = graph.getMark();
-
-            DummyAnchorNode 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();
-            }
-
-            AbstractEndNode endAfter = createNewMerge(fixed, stateAfter);
-            AbstractMergeNode mergeAfter = endAfter.merge();
-            fixedNodes.add(endAfter);
-            final Set<Node> duplicatedNodes = buildDuplicatedNodeSet(fixedNodes, stateAfter);
-            mergeAfter.clearEnds();
-            expandDuplicated(duplicatedNodes, mergeAfter);
-
-            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, graph, duplicatedNodes.size(), (DuplicationReplacement) null);
-                } else {
-                    Map<Node, Node> replace = Node.newMap();
-                    replace.put(replacements.get(endIndex).object(), replacements.get(endIndex));
-                    duplicates = graph.addDuplicates(duplicatedNodes, graph, duplicatedNodes.size(), 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
-                FixedWithNextNode anchorDuplicate = (FixedWithNextNode) duplicates.get(anchor);
-                // move dependencies on the ValueAnchorNode to the previous BeginNode
-                AbstractBeginNode prevBegin = AbstractBeginNode.prevBegin(forwardEnd);
-                anchorDuplicate.replaceAtUsages(InputType.Guard, prevBegin);
-                anchorDuplicate.replaceAtUsages(InputType.Anchor, prevBegin);
-                assert anchorDuplicate.hasNoUsages();
-
-                FixedNode next = anchorDuplicate.next();
-                anchorDuplicate.setNext(null);
-                ((FixedWithNextNode) forwardEnd.predecessor()).setNext(next);
-                anchorDuplicate.safeDelete();
-
-                // re-wire the phi duplicates to the correct input
-                for (PhiNode phi : phiSnapshot) {
-                    PhiNode phiDuplicate = (PhiNode) duplicates.get(phi);
-                    phiDuplicate.replaceAtUsages(phi.valueAt(forwardEnd));
-                    phiDuplicate.safeDelete();
-                }
-                endIndex++;
-            }
-            GraphUtil.killCFG(merge);
-            for (AbstractEndNode 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);
-                }
-            }
-            canonicalizer.applyIncremental(graph, phaseContext, startMark);
-            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 DummyAnchorNode addValueAnchor() {
-            DummyAnchorNode anchor = graph.add(new DummyAnchorNode());
-            graph.addAfterFixed(merge, anchor);
-            merge.replaceAtUsages(InputType.Guard, anchor);
-            merge.replaceAtUsages(InputType.Anchor, 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 Set<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);
-            Set<Node> result = Node.newSet();
-            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 AbstractEndNode createNewMerge(FixedNode successor, FrameState stateAfterMerge) {
-            MergeNode newBottomMerge = graph.add(new MergeNode());
-            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>Inputs of type {@link InputType#Value} into the duplicated set will be rerouted to a
-         * new phi node.</li>
-         * <li>Inputs of type {@link InputType#Association}, {@link InputType#Condition} and
-         * {@link InputType#State} into the duplicated set will be rerouted to a duplicated version
-         * of the inside node.</li>
-         * <li>Dependencies into the duplicated nodes will be replaced with dependencies on the
-         * merge.</li>
-         * <li>Inputs of type {@link InputType#Association}, {@link InputType#Condition} and
-         * {@link InputType#State} to outside the duplicated set will cause the outside node to be
-         * pulled into the duplicated set.</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(Set<Node> duplicatedNodes, AbstractMergeNode newBottomMerge) {
-            Deque<Node> worklist = new ArrayDeque<>(duplicatedNodes);
-
-            while (!worklist.isEmpty()) {
-                Node duplicated = worklist.remove();
-                processUsages(duplicated, duplicatedNodes, newBottomMerge, worklist);
-                processInputs(duplicated, duplicatedNodes, worklist);
-            }
-        }
-
-        private void processUsages(Node duplicated, Set<Node> duplicatedNodes, AbstractMergeNode newBottomMerge, Deque<Node> worklist) {
-            Set<Node> unique = Node.newSet();
-            duplicated.usages().snapshotTo(unique);
-            Node newOutsideClone = null;
-            for (Node usage : unique) {
-                if (!duplicatedNodes.contains(usage)) {
-                    NodePosIterator iter = usage.inputs().iterator();
-                    while (iter.hasNext()) {
-                        Position pos = iter.nextPosition();
-                        if (pos.get(usage) == duplicated) {
-                            switch (pos.getInputType()) {
-                                case Extension:
-                                case Condition:
-                                case State:
-                                    // clone the offending node to the outside
-                                    if (newOutsideClone == null) {
-                                        newOutsideClone = duplicated.copyWithInputs();
-                                        // this might cause other nodes to have outside usages
-                                        for (Node input : newOutsideClone.inputs()) {
-                                            if (duplicatedNodes.contains(input)) {
-                                                worklist.add(input);
-                                            }
-                                        }
-                                    }
-                                    pos.set(usage, newOutsideClone);
-                                    break;
-                                case Guard:
-                                case Anchor:
-                                    // re-route dependencies to the merge
-                                    pos.set(usage, newBottomMerge);
-                                    break;
-                                case Value:
-                                    // introduce a new phi
-                                    ValueNode node = (ValueNode) duplicated;
-                                    PhiNode newPhi = bottomPhis.get(node);
-                                    if (newPhi == null) {
-                                        newPhi = graph.addWithoutUnique(new ValuePhiNode(node.stamp().unrestricted(), newBottomMerge));
-                                        bottomPhis.put(node, newPhi);
-                                        newPhi.addInput(node);
-                                    }
-                                    pos.set(usage, newPhi);
-                                    break;
-                                case Association:
-                                default:
-                                    throw GraalInternalError.shouldNotReachHere();
-                            }
-                        }
-                    }
-                }
-            }
-        }
-
-        private void processInputs(Node duplicated, Set<Node> duplicatedNodes, Deque<Node> worklist) {
-            // check if this node has an input that lies outside and cannot be shared
-            NodePosIterator iter = duplicated.inputs().iterator();
-            while (iter.hasNext()) {
-                Position pos = iter.nextPosition();
-                Node input = pos.get(duplicated);
-                if (input != null && !duplicatedNodes.contains(input)) {
-                    switch (pos.getInputType()) {
-                        case Extension:
-                        case Condition:
-                        case State:
-                            if (input != merge) {
-                                duplicatedNodes.add(input);
-                                worklist.add(input);
-                            }
-                            break;
-                        case Association:
-                        case Guard:
-                        case Anchor:
-                        case Value:
-                            // no change needed
-                            break;
-                        default:
-                            throw GraalInternalError.shouldNotReachHere();
-                    }
-                }
-            }
-        }
-    }
-}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java	Wed Mar 18 10:01:25 2015 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java	Wed Mar 18 10:07:47 2015 -0700
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.phases.common.inlining.info;
 
-import static com.oracle.graal.compiler.common.GraalOptions.*;
-
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
@@ -39,10 +37,8 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.util.*;
-import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.common.inlining.*;
 import com.oracle.graal.phases.common.inlining.info.elem.*;
-import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.phases.util.*;
 
 /**
@@ -52,8 +48,6 @@
  */
 public class MultiTypeGuardInlineInfo extends AbstractInlineInfo {
 
-    private static final DebugMetric metricInliningTailDuplication = Debug.metric("InliningTailDuplication");
-
     private final List<ResolvedJavaMethod> concretes;
     private final double[] methodProbabilities;
     private final double maximumMethodProbability;
@@ -170,7 +164,6 @@
         int numberOfMethods = concretes.size();
         FixedNode continuation = invoke.next();
 
-        ValueNode originalReceiver = ((MethodCallTargetNode) invoke.callTarget()).receiver();
         // setup merge and phi nodes for results and exceptions
         AbstractMergeNode returnMerge = graph.add(new MergeNode());
         returnMerge.setStateAfter(invoke.stateAfter());
@@ -257,35 +250,6 @@
             replacementNodes.add(null);
         }
 
-        if (OptTailDuplication.getValue()) {
-            /*
-             * 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).callTarget() instanceof MethodCallTargetNode &&
-                                ((MethodCallTargetNode) ((InvokeNode) current).callTarget()).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);
-                PhaseContext phaseContext = new PhaseContext(providers);
-                CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
-                if (ImmutableCode.getValue()) {
-                    canonicalizer.disableReadCanonicalization();
-                }
-                TailDuplicationPhase.tailDuplicate(returnMerge, TailDuplicationPhase.TRUE_DECISION, replacementNodes, phaseContext, canonicalizer);
-            }
-        }
-
         Collection<Node> canonicalizeNodes = new ArrayList<>();
         // do the actual inlining for every invoke
         for (int i = 0; i < numberOfMethods; i++) {
--- a/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARCScratchRegister.java	Wed Mar 18 10:01:25 2015 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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.sparc;
-
-import com.oracle.graal.api.code.*;
-
-public final class SPARCScratchRegister implements AutoCloseable {
-    private final ThreadLocal<Boolean> locked = new ThreadLocal<>();
-    private final ThreadLocal<Exception> where = new ThreadLocal<>();
-    private final Register register;
-    private static final SPARCScratchRegister scratch1 = new SPARCScratchRegister(SPARC.g3);
-    private static final SPARCScratchRegister scratch2 = new SPARCScratchRegister(SPARC.g1);
-    private static final boolean LOG_REQUEST_STACK = false;
-
-    private SPARCScratchRegister(Register register) {
-        super();
-        this.register = register;
-    }
-
-    public Register getRegister() {
-        if (locked.get() == null) {
-            locked.set(false);
-        }
-        boolean isLocked = locked.get();
-        if (isLocked) {
-            if (LOG_REQUEST_STACK) {
-                where.get().printStackTrace();
-            }
-            throw new RuntimeException("Temp Register is already taken!");
-        } else {
-            if (LOG_REQUEST_STACK) {
-                where.set(new Exception());
-            }
-            locked.set(true);
-            return register;
-        }
-    }
-
-    public void close() {
-        boolean isLocked = locked.get();
-        if (isLocked) {
-            locked.set(false);
-        } else {
-            throw new RuntimeException("Temp Register is not taken!");
-        }
-    }
-
-    public static SPARCScratchRegister get() {
-        if (scratch1.isLocked()) {
-            return scratch2;
-        } else {
-            return scratch1;
-        }
-    }
-
-    public boolean isLocked() {
-        Boolean isLocked = locked.get();
-        if (isLocked == null) {
-            return false;
-        } else {
-            return isLocked;
-        }
-    }
-}
--- a/graal/com.oracle.graal.truffle.hotspot.sparc/src/com/oracle/graal/truffle/hotspot/sparc/SPARCOptimizedCallTargetInstumentationFactory.java	Wed Mar 18 10:01:25 2015 -0700
+++ b/graal/com.oracle.graal.truffle.hotspot.sparc/src/com/oracle/graal/truffle/hotspot/sparc/SPARCOptimizedCallTargetInstumentationFactory.java	Wed Mar 18 10:07:47 2015 -0700
@@ -35,11 +35,11 @@
 import com.oracle.graal.api.runtime.*;
 import com.oracle.graal.asm.*;
 import com.oracle.graal.asm.sparc.*;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler.ScratchRegister;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.framemap.*;
-import com.oracle.graal.sparc.*;
 import com.oracle.graal.truffle.*;
 import com.oracle.graal.truffle.hotspot.*;
 
@@ -53,7 +53,7 @@
             protected void injectTailCallCode(HotSpotVMConfig config, HotSpotRegistersProvider registers) {
                 @SuppressWarnings("hiding")
                 SPARCMacroAssembler asm = (SPARCMacroAssembler) this.asm;
-                try (SPARCScratchRegister scratch = SPARCScratchRegister.get()) {
+                try (ScratchRegister scratch = asm.getScratchRegister()) {
                     Register thisRegister = codeCache.getRegisterConfig().getCallingConventionRegisters(JavaCall, Object)[0];
                     Register spillRegister = scratch.getRegister();
                     Label doProlog = new Label();