changeset 22623:ed489bbcccbb

Properly handle metaspace constants in switch statements.
author Roland Schatz <roland.schatz@oracle.com>
date Mon, 14 Sep 2015 16:34:26 +0200
parents 9055e22b8661
children 9aeba02d5aae
files graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64AddressLowering.java graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotStrategySwitchOp.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotStrategySwitchOp.java graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotResolvedObjectTypeTest.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HubGetClassNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/KlassLayoutHelperNode.java graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/SwitchStrategy.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java
diffstat 16 files changed, 517 insertions(+), 211 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64AddressLowering.java	Sun Sep 13 21:03:52 2015 +0200
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64AddressLowering.java	Mon Sep 14 16:34:26 2015 +0200
@@ -114,8 +114,9 @@
             return null;
         }
 
-        if (node.isConstant()) {
-            return improveConstDisp(address, node, node.asJavaConstant(), null, shift);
+        JavaConstant c = node.asJavaConstant();
+        if (c != null) {
+            return improveConstDisp(address, node, c, null, shift);
         } else {
             if (node.stamp() instanceof IntegerStamp && ((IntegerStamp) node.stamp()).getBits() == 64) {
                 if (node instanceof ZeroExtendNode) {
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Sun Sep 13 21:03:52 2015 +0200
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Mon Sep 14 16:34:26 2015 +0200
@@ -1469,11 +1469,15 @@
         append(new ReturnOp(operand));
     }
 
+    protected StrategySwitchOp createStrategySwitchOp(SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Variable key, AllocatableValue temp) {
+        return new StrategySwitchOp(strategy, keyTargets, defaultTarget, key, temp);
+    }
+
     @Override
     public void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget) {
         // a temp is needed for loading object constants
         boolean needsTemp = key.getPlatformKind() == JavaKind.Object;
-        append(new StrategySwitchOp(strategy, keyTargets, defaultTarget, key, needsTemp ? newVariable(key.getLIRKind()) : Value.ILLEGAL));
+        append(createStrategySwitchOp(strategy, keyTargets, defaultTarget, key, needsTemp ? newVariable(key.getLIRKind()) : Value.ILLEGAL));
     }
 
     @Override
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Sun Sep 13 21:03:52 2015 +0200
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Mon Sep 14 16:34:26 2015 +0200
@@ -426,15 +426,19 @@
 
     @Override
     public void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget) {
-        Value scratchValue = newVariable(key.getLIRKind());
+        AllocatableValue scratchValue = newVariable(key.getLIRKind());
         AllocatableValue base = AllocatableValue.ILLEGAL;
-        for (JavaConstant c : strategy.keyConstants) {
-            if (!canInlineConstant(c)) {
+        for (Constant c : strategy.getKeyConstants()) {
+            if (!(c instanceof JavaConstant) || !canInlineConstant((JavaConstant) c)) {
                 base = getConstantTableBase();
                 break;
             }
         }
-        append(new StrategySwitchOp(base, strategy, keyTargets, defaultTarget, key, scratchValue));
+        append(createStrategySwitchOp(base, strategy, keyTargets, defaultTarget, key, scratchValue));
+    }
+
+    protected StrategySwitchOp createStrategySwitchOp(AllocatableValue base, SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Variable key, AllocatableValue scratchValue) {
+        return new StrategySwitchOp(base, strategy, keyTargets, defaultTarget, key, scratchValue);
     }
 
     @Override
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java	Sun Sep 13 21:03:52 2015 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java	Mon Sep 14 16:34:26 2015 +0200
@@ -626,23 +626,32 @@
                 LIRKind kind = gen.getLIRKind(x.value().stamp());
                 Value key = gen.emitConstant(kind, x.keyAt(0));
                 gen.emitCompareBranch(kind.getPlatformKind(), gen.load(operand(x.value())), key, Condition.EQ, false, getLIRBlock(x.keySuccessor(0)), defaultTarget, probability);
-            } else {
+            } else if (x instanceof IntegerSwitchNode && x.isSorted()) {
+                IntegerSwitchNode intSwitch = (IntegerSwitchNode) x;
                 LabelRef[] keyTargets = new LabelRef[keyCount];
                 JavaConstant[] keyConstants = new JavaConstant[keyCount];
                 double[] keyProbabilities = new double[keyCount];
-                JavaKind keyKind = x.keyAt(0).getJavaKind();
+                JavaKind keyKind = intSwitch.keyAt(0).getJavaKind();
+                for (int i = 0; i < keyCount; i++) {
+                    keyTargets[i] = getLIRBlock(intSwitch.keySuccessor(i));
+                    keyConstants[i] = intSwitch.keyAt(i);
+                    keyProbabilities[i] = intSwitch.keyProbability(i);
+                    assert keyConstants[i].getJavaKind() == keyKind;
+                }
+                gen.emitStrategySwitch(keyConstants, keyProbabilities, keyTargets, defaultTarget, value);
+            } else {
+                // keyKind != JavaKind.Int || !x.isSorted()
+                LabelRef[] keyTargets = new LabelRef[keyCount];
+                Constant[] keyConstants = new Constant[keyCount];
+                double[] keyProbabilities = new double[keyCount];
                 for (int i = 0; i < keyCount; i++) {
                     keyTargets[i] = getLIRBlock(x.keySuccessor(i));
                     keyConstants[i] = x.keyAt(i);
                     keyProbabilities[i] = x.keyProbability(i);
-                    assert keyConstants[i].getJavaKind() == keyKind;
                 }
-                if (keyKind != JavaKind.Int || !x.isSorted()) {
-                    // hopefully only a few entries
-                    gen.emitStrategySwitch(new SwitchStrategy.SequentialStrategy(keyProbabilities, keyConstants), value, keyTargets, defaultTarget);
-                } else {
-                    gen.emitStrategySwitch(keyConstants, keyProbabilities, keyTargets, defaultTarget, value);
-                }
+
+                // hopefully only a few entries
+                gen.emitStrategySwitch(new SwitchStrategy.SequentialStrategy(keyProbabilities, keyConstants), value, keyTargets, defaultTarget);
             }
         }
     }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Sun Sep 13 21:03:52 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Mon Sep 14 16:34:26 2015 +0200
@@ -22,43 +22,88 @@
  */
 package com.oracle.graal.hotspot.amd64;
 
-import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.*;
-import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64RMOp.*;
-import static com.oracle.graal.asm.amd64.AMD64Assembler.OperandSize.*;
-import static com.oracle.graal.hotspot.HotSpotBackend.*;
-import static com.oracle.graal.lir.LIRValueUtil.*;
-import static jdk.internal.jvmci.amd64.AMD64.*;
+import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.CMP;
+import static com.oracle.graal.asm.amd64.AMD64Assembler.AMD64RMOp.TEST;
+import static com.oracle.graal.asm.amd64.AMD64Assembler.OperandSize.DWORD;
+import static com.oracle.graal.asm.amd64.AMD64Assembler.OperandSize.QWORD;
+import static com.oracle.graal.hotspot.HotSpotBackend.FETCH_UNROLL_INFO;
+import static com.oracle.graal.hotspot.HotSpotBackend.UNCOMMON_TRAP;
+import static com.oracle.graal.lir.LIRValueUtil.asConstant;
+import static com.oracle.graal.lir.LIRValueUtil.isConstantValue;
+import static jdk.internal.jvmci.amd64.AMD64.cpuxmmRegisters;
+import static jdk.internal.jvmci.amd64.AMD64.rbp;
+
+import java.util.List;
+import java.util.Map;
 
-import java.util.*;
-
-import jdk.internal.jvmci.amd64.*;
-import jdk.internal.jvmci.code.*;
-import jdk.internal.jvmci.common.*;
-import jdk.internal.jvmci.hotspot.*;
+import jdk.internal.jvmci.amd64.AMD64;
+import jdk.internal.jvmci.code.CallingConvention;
+import jdk.internal.jvmci.code.Register;
+import jdk.internal.jvmci.code.RegisterConfig;
+import jdk.internal.jvmci.code.RegisterValue;
+import jdk.internal.jvmci.code.StackSlot;
+import jdk.internal.jvmci.code.StackSlotValue;
+import jdk.internal.jvmci.code.VirtualStackSlot;
+import jdk.internal.jvmci.common.JVMCIError;
+import jdk.internal.jvmci.hotspot.HotSpotCompressedNullConstant;
+import jdk.internal.jvmci.hotspot.HotSpotConstant;
+import jdk.internal.jvmci.hotspot.HotSpotMetaspaceConstant;
+import jdk.internal.jvmci.hotspot.HotSpotObjectConstant;
+import jdk.internal.jvmci.hotspot.HotSpotVMConfig;
 import jdk.internal.jvmci.hotspot.HotSpotVMConfig.CompressEncoding;
-import jdk.internal.jvmci.meta.*;
+import jdk.internal.jvmci.meta.AllocatableValue;
+import jdk.internal.jvmci.meta.Constant;
+import jdk.internal.jvmci.meta.DeoptimizationAction;
+import jdk.internal.jvmci.meta.DeoptimizationReason;
+import jdk.internal.jvmci.meta.JavaConstant;
+import jdk.internal.jvmci.meta.JavaKind;
+import jdk.internal.jvmci.meta.LIRKind;
+import jdk.internal.jvmci.meta.PlatformKind;
+import jdk.internal.jvmci.meta.PrimitiveConstant;
+import jdk.internal.jvmci.meta.Value;
 
 import com.oracle.graal.asm.amd64.AMD64Address.Scale;
 import com.oracle.graal.asm.amd64.AMD64Assembler.AMD64MIOp;
 import com.oracle.graal.asm.amd64.AMD64Assembler.OperandSize;
-import com.oracle.graal.compiler.amd64.*;
-import com.oracle.graal.compiler.common.*;
-import com.oracle.graal.compiler.common.spi.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.hotspot.*;
+import com.oracle.graal.compiler.amd64.AMD64LIRGenerator;
+import com.oracle.graal.compiler.common.GraalOptions;
+import com.oracle.graal.compiler.common.spi.ForeignCallLinkage;
+import com.oracle.graal.compiler.common.spi.LIRKindTool;
+import com.oracle.graal.debug.Debug;
+import com.oracle.graal.hotspot.HotSpotBackend;
+import com.oracle.graal.hotspot.HotSpotForeignCallLinkage;
+import com.oracle.graal.hotspot.HotSpotLIRGenerator;
+import com.oracle.graal.hotspot.HotSpotLockStack;
 import com.oracle.graal.hotspot.amd64.AMD64HotSpotMove.StoreRbpOp;
-import com.oracle.graal.hotspot.debug.*;
-import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.hotspot.stubs.*;
-import com.oracle.graal.lir.*;
+import com.oracle.graal.hotspot.debug.BenchmarkCounters;
+import com.oracle.graal.hotspot.meta.HotSpotProviders;
+import com.oracle.graal.hotspot.stubs.Stub;
+import com.oracle.graal.lir.ConstantValue;
+import com.oracle.graal.lir.LIR;
+import com.oracle.graal.lir.LIRFrameState;
+import com.oracle.graal.lir.LIRInstruction;
+import com.oracle.graal.lir.LIRInstructionClass;
+import com.oracle.graal.lir.LabelRef;
 import com.oracle.graal.lir.StandardOp.NoOp;
 import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
-import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.SwitchStrategy;
+import com.oracle.graal.lir.Variable;
+import com.oracle.graal.lir.amd64.AMD64AddressValue;
+import com.oracle.graal.lir.amd64.AMD64BinaryConsumer;
+import com.oracle.graal.lir.amd64.AMD64CCall;
+import com.oracle.graal.lir.amd64.AMD64ControlFlow.StrategySwitchOp;
+import com.oracle.graal.lir.amd64.AMD64FrameMapBuilder;
+import com.oracle.graal.lir.amd64.AMD64LIRInstruction;
+import com.oracle.graal.lir.amd64.AMD64Move;
 import com.oracle.graal.lir.amd64.AMD64Move.LeaDataOp;
 import com.oracle.graal.lir.amd64.AMD64Move.MoveFromRegOp;
-import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.lir.framemap.*;
-import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.lir.amd64.AMD64RestoreRegistersOp;
+import com.oracle.graal.lir.amd64.AMD64SaveRegistersOp;
+import com.oracle.graal.lir.amd64.AMD64ZapRegistersOp;
+import com.oracle.graal.lir.asm.CompilationResultBuilder;
+import com.oracle.graal.lir.framemap.FrameMapBuilder;
+import com.oracle.graal.lir.gen.DefaultLIRKindTool;
+import com.oracle.graal.lir.gen.LIRGenerationResult;
 
 /**
  * LIR generator specialized for AMD64 HotSpot.
@@ -672,4 +717,8 @@
         append(new AMD64PrefetchOp(asAddressValue(address), config.allocatePrefetchInstr));
     }
 
+    @Override
+    protected StrategySwitchOp createStrategySwitchOp(SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Variable key, AllocatableValue temp) {
+        return new AMD64HotSpotStrategySwitchOp(strategy, keyTargets, defaultTarget, key, temp);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotStrategySwitchOp.java	Mon Sep 14 16:34:26 2015 +0200
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2015, 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.hotspot.amd64;
+
+import jdk.internal.jvmci.code.Register;
+import jdk.internal.jvmci.code.ValueUtil;
+import jdk.internal.jvmci.hotspot.HotSpotMetaspaceConstant;
+import jdk.internal.jvmci.meta.Constant;
+import jdk.internal.jvmci.meta.Value;
+
+import com.oracle.graal.asm.NumUtil;
+import com.oracle.graal.asm.amd64.AMD64Address;
+import com.oracle.graal.asm.amd64.AMD64MacroAssembler;
+import com.oracle.graal.lir.LIRInstructionClass;
+import com.oracle.graal.lir.LabelRef;
+import com.oracle.graal.lir.SwitchStrategy;
+import com.oracle.graal.lir.amd64.AMD64ControlFlow;
+import com.oracle.graal.lir.asm.CompilationResultBuilder;
+
+final class AMD64HotSpotStrategySwitchOp extends AMD64ControlFlow.StrategySwitchOp {
+    public static final LIRInstructionClass<AMD64HotSpotStrategySwitchOp> TYPE = LIRInstructionClass.create(AMD64HotSpotStrategySwitchOp.class);
+
+    public AMD64HotSpotStrategySwitchOp(SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value scratch) {
+        super(TYPE, strategy, keyTargets, defaultTarget, key, scratch);
+    }
+
+    @Override
+    public void emitCode(final CompilationResultBuilder crb, final AMD64MacroAssembler masm) {
+        strategy.run(new HotSpotSwitchClosure(ValueUtil.asRegister(key), crb, masm));
+    }
+
+    public class HotSpotSwitchClosure extends SwitchClosure {
+
+        protected HotSpotSwitchClosure(Register keyRegister, CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+            super(keyRegister, crb, masm);
+        }
+
+        @Override
+        protected void emitComparison(Constant c) {
+            if (c instanceof HotSpotMetaspaceConstant) {
+                HotSpotMetaspaceConstant meta = (HotSpotMetaspaceConstant) c;
+                if (meta.isCompressed()) {
+                    crb.recordInlineDataInCode(meta);
+
+                    assert NumUtil.isInt(meta.rawValue());
+                    masm.cmpl(keyRegister, (int) meta.rawValue());
+                } else {
+                    AMD64Address addr = (AMD64Address) crb.recordDataReferenceInCode(meta, 8);
+                    masm.cmpq(keyRegister, addr);
+                }
+            } else {
+                super.emitComparison(c);
+            }
+        }
+    }
+}
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Sun Sep 13 21:03:52 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java	Mon Sep 14 16:34:26 2015 +0200
@@ -48,6 +48,7 @@
 import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.lir.sparc.*;
+import com.oracle.graal.lir.sparc.SPARCControlFlow.StrategySwitchOp;
 import com.oracle.graal.lir.sparc.SPARCMove.CompareAndSwapOp;
 import com.oracle.graal.lir.sparc.SPARCMove.LoadOp;
 import com.oracle.graal.lir.sparc.SPARCMove.NullCheckOp;
@@ -488,4 +489,9 @@
         }
         return this.safepointAddressValue;
     }
+
+    @Override
+    protected StrategySwitchOp createStrategySwitchOp(AllocatableValue base, SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Variable key, AllocatableValue scratchValue) {
+        return new SPARCHotSpotStrategySwitchOp(base, strategy, keyTargets, defaultTarget, key, scratchValue);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotStrategySwitchOp.java	Mon Sep 14 16:34:26 2015 +0200
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2015, 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.hotspot.sparc;
+
+import static com.oracle.graal.asm.sparc.SPARCAssembler.CBCOND;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.Annul.ANNUL;
+import static com.oracle.graal.asm.sparc.SPARCAssembler.BranchPredict.PREDICT_TAKEN;
+import static jdk.internal.jvmci.code.ValueUtil.asRegister;
+import jdk.internal.jvmci.code.Register;
+import jdk.internal.jvmci.hotspot.HotSpotMetaspaceConstant;
+import jdk.internal.jvmci.meta.Constant;
+import jdk.internal.jvmci.meta.Value;
+import jdk.internal.jvmci.sparc.SPARC;
+import jdk.internal.jvmci.sparc.SPARC.CPUFeature;
+
+import com.oracle.graal.asm.Assembler.LabelHint;
+import com.oracle.graal.asm.Label;
+import com.oracle.graal.asm.sparc.SPARCAssembler.CC;
+import com.oracle.graal.asm.sparc.SPARCAssembler.ConditionFlag;
+import com.oracle.graal.asm.sparc.SPARCMacroAssembler;
+import com.oracle.graal.compiler.common.calc.Condition;
+import com.oracle.graal.lir.LIRInstructionClass;
+import com.oracle.graal.lir.LabelRef;
+import com.oracle.graal.lir.SwitchStrategy;
+import com.oracle.graal.lir.asm.CompilationResultBuilder;
+import com.oracle.graal.lir.sparc.SPARCControlFlow;
+import com.oracle.graal.lir.sparc.SPARCDelayedControlTransfer;
+import com.oracle.graal.lir.sparc.SPARCMove;
+
+final class SPARCHotSpotStrategySwitchOp extends SPARCControlFlow.StrategySwitchOp {
+    public static final LIRInstructionClass<SPARCHotSpotStrategySwitchOp> TYPE = LIRInstructionClass.create(SPARCHotSpotStrategySwitchOp.class);
+
+    public SPARCHotSpotStrategySwitchOp(Value constantTableBase, SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value scratch) {
+        super(TYPE, constantTableBase, strategy, keyTargets, defaultTarget, key, scratch);
+    }
+
+    public class HotSpotSwitchClosure extends SwitchClosure {
+        protected HotSpotSwitchClosure(Register keyRegister, Register constantBaseRegister, CompilationResultBuilder crb, SPARCMacroAssembler masm) {
+            super(keyRegister, constantBaseRegister, crb, masm);
+        }
+
+        @Override
+        protected void conditionalJump(int index, Condition condition, Label target) {
+            if (keyConstants[index] instanceof HotSpotMetaspaceConstant) {
+                HotSpotMetaspaceConstant constant = (HotSpotMetaspaceConstant) keyConstants[index];
+                CC conditionCode = constant.isCompressed() ? CC.Icc : CC.Xcc;
+                ConditionFlag conditionFlag = SPARCControlFlow.fromCondition(conditionCode, condition, false);
+                LabelHint hint = requestHint(masm, target);
+
+                // Load constant takes one instruction
+                int cbCondPosition = masm.position() + SPARC.INSTRUCTION_SIZE;
+                boolean canUseShortBranch = masm.hasFeature(CPUFeature.CBCOND) && SPARCControlFlow.isShortBranch(masm, cbCondPosition, hint, target);
+
+                Register scratchRegister = asRegister(scratch);
+                final int byteCount = constant.isCompressed() ? 4 : 8;
+                Runnable recordReference = () -> crb.recordDataReferenceInCode(constant, byteCount);
+                SPARCMove.loadFromConstantTable(crb, masm, byteCount, asRegister(constantTableBase), scratchRegister, SPARCDelayedControlTransfer.DUMMY, recordReference);
+
+                if (canUseShortBranch) {
+                    CBCOND.emit(masm, conditionFlag, conditionCode == CC.Xcc, keyRegister, scratchRegister, target);
+                } else {
+                    masm.cmp(keyRegister, scratchRegister);
+                    masm.bpcc(conditionFlag, ANNUL, target, conditionCode, PREDICT_TAKEN);
+                    masm.nop();  // delay slot
+                }
+            } else {
+                super.conditionalJump(index, condition, target);
+            }
+        }
+    }
+
+    @Override
+    protected int estimateEmbeddedSize(Constant c) {
+        if (c instanceof HotSpotMetaspaceConstant) {
+            return ((HotSpotMetaspaceConstant) c).isCompressed() ? 4 : 8;
+        } else {
+            return super.estimateEmbeddedSize(c);
+        }
+    }
+}
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotResolvedObjectTypeTest.java	Sun Sep 13 21:03:52 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotResolvedObjectTypeTest.java	Mon Sep 14 16:34:26 2015 +0200
@@ -42,7 +42,7 @@
 
     @Test
     public void testKlassLayoutHelper() {
-        JavaConstant klass = HotSpotResolvedObjectTypeImpl.fromObjectClass(this.getClass()).klass();
+        Constant klass = HotSpotResolvedObjectTypeImpl.fromObjectClass(this.getClass()).klass();
         MemoryAccessProvider memoryAccess = getProviders().getConstantReflection().getMemoryAccessProvider();
         HotSpotVMConfig config = runtime().getConfig();
         Constant c = StampFactory.forKind(JavaKind.Int).readConstant(memoryAccess, klass, config.klassLayoutHelperOffset);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HubGetClassNode.java	Sun Sep 13 21:03:52 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HubGetClassNode.java	Mon Sep 14 16:34:26 2015 +0200
@@ -59,7 +59,7 @@
         } else {
             MetaAccessProvider metaAccess = tool.getMetaAccess();
             if (metaAccess != null && hub.isConstant()) {
-                ResolvedJavaType exactType = tool.getConstantReflection().asJavaType(hub.asJavaConstant());
+                ResolvedJavaType exactType = tool.getConstantReflection().asJavaType(hub.asConstant());
                 if (exactType != null) {
                     return ConstantNode.forConstant(exactType.getJavaClass(), metaAccess);
                 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/KlassLayoutHelperNode.java	Sun Sep 13 21:03:52 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/KlassLayoutHelperNode.java	Mon Sep 14 16:34:26 2015 +0200
@@ -85,7 +85,7 @@
         } else {
             if (klass.isConstant()) {
                 if (!klass.asConstant().isDefaultForKind()) {
-                    Constant constant = stamp().readConstant(tool.getConstantReflection().getMemoryAccessProvider(), klass.asJavaConstant(), config.klassLayoutHelperOffset);
+                    Constant constant = stamp().readConstant(tool.getConstantReflection().getMemoryAccessProvider(), klass.asConstant(), config.klassLayoutHelperOffset);
                     return ConstantNode.forConstant(stamp(), constant, tool.getMetaAccess());
                 }
             }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java	Sun Sep 13 21:03:52 2015 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java	Mon Sep 14 16:34:26 2015 +0200
@@ -125,19 +125,23 @@
         }
     }
 
-    public static final class StrategySwitchOp extends AMD64BlockEndOp {
+    public static class StrategySwitchOp extends AMD64BlockEndOp {
         public static final LIRInstructionClass<StrategySwitchOp> TYPE = LIRInstructionClass.create(StrategySwitchOp.class);
-        protected final JavaConstant[] keyConstants;
+        protected final Constant[] keyConstants;
         private final LabelRef[] keyTargets;
         private LabelRef defaultTarget;
         @Alive({REG}) protected Value key;
         @Temp({REG, ILLEGAL}) protected Value scratch;
-        private final SwitchStrategy strategy;
+        protected final SwitchStrategy strategy;
 
         public StrategySwitchOp(SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value scratch) {
-            super(TYPE);
+            this(TYPE, strategy, keyTargets, defaultTarget, key, scratch);
+        }
+
+        protected StrategySwitchOp(LIRInstructionClass<? extends StrategySwitchOp> c, SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value scratch) {
+            super(c);
             this.strategy = strategy;
-            this.keyConstants = strategy.keyConstants;
+            this.keyConstants = strategy.getKeyConstants();
             this.keyTargets = keyTargets;
             this.defaultTarget = defaultTarget;
             this.key = key;
@@ -149,35 +153,50 @@
 
         @Override
         public void emitCode(final CompilationResultBuilder crb, final AMD64MacroAssembler masm) {
-            final Register keyRegister = asRegister(key);
+            strategy.run(new SwitchClosure(asRegister(key), crb, masm));
+        }
+
+        public class SwitchClosure extends BaseSwitchClosure {
+
+            protected final Register keyRegister;
+            protected final CompilationResultBuilder crb;
+            protected final AMD64MacroAssembler masm;
+
+            protected SwitchClosure(Register keyRegister, CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+                super(crb, masm, keyTargets, defaultTarget);
+                this.keyRegister = keyRegister;
+                this.crb = crb;
+                this.masm = masm;
+            }
 
-            BaseSwitchClosure closure = new BaseSwitchClosure(crb, masm, keyTargets, defaultTarget) {
-                @Override
-                protected void conditionalJump(int index, Condition condition, Label target) {
-                    switch (keyConstants[index].getJavaKind()) {
-                        case Int:
-                            if (crb.codeCache.needsDataPatch(keyConstants[index])) {
-                                crb.recordInlineDataInCode(keyConstants[index]);
-                            }
-                            long lc = keyConstants[index].asLong();
-                            assert NumUtil.isInt(lc);
-                            masm.cmpl(keyRegister, (int) lc);
-                            break;
-                        case Long:
-                            masm.cmpq(keyRegister, (AMD64Address) crb.asLongConstRef(keyConstants[index]));
-                            break;
-                        case Object:
-                            assert condition == Condition.EQ || condition == Condition.NE;
-                            AMD64Move.const2reg(crb, masm, scratch, keyConstants[index]);
-                            masm.cmpptr(keyRegister, asRegister(scratch));
-                            break;
-                        default:
-                            throw new JVMCIError("switch only supported for int, long and object");
-                    }
-                    masm.jcc(intCond(condition), target);
+            protected void emitComparison(Constant c) {
+                JavaConstant jc = (JavaConstant) c;
+                switch (jc.getJavaKind()) {
+                    case Int:
+                        if (crb.codeCache.needsDataPatch(jc)) {
+                            crb.recordInlineDataInCode(jc);
+                        }
+                        long lc = jc.asLong();
+                        assert NumUtil.isInt(lc);
+                        masm.cmpl(keyRegister, (int) lc);
+                        break;
+                    case Long:
+                        masm.cmpq(keyRegister, (AMD64Address) crb.asLongConstRef(jc));
+                        break;
+                    case Object:
+                        AMD64Move.const2reg(crb, masm, scratch, jc);
+                        masm.cmpptr(keyRegister, asRegister(scratch));
+                        break;
+                    default:
+                        throw new JVMCIError("switch only supported for int, long and object");
                 }
-            };
-            strategy.run(closure);
+            }
+
+            @Override
+            protected void conditionalJump(int index, Condition condition, Label target) {
+                emitComparison(keyConstants[index]);
+                masm.jcc(intCond(condition), target);
+            }
         }
     }
 
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Sun Sep 13 21:03:52 2015 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Mon Sep 14 16:34:26 2015 +0200
@@ -307,7 +307,7 @@
         }
     }
 
-    private static boolean isShortBranch(SPARCAssembler asm, int position, LabelHint hint, Label label) {
+    public static boolean isShortBranch(SPARCAssembler asm, int position, LabelHint hint, Label label) {
         int disp = 0;
         boolean dispValid = true;
         if (label.isBound()) {
@@ -395,9 +395,9 @@
         return true;
     }
 
-    public static final class StrategySwitchOp extends SPARCBlockEndOp {
+    public static class StrategySwitchOp extends SPARCBlockEndOp {
         public static final LIRInstructionClass<StrategySwitchOp> TYPE = LIRInstructionClass.create(StrategySwitchOp.class);
-        protected JavaConstant[] keyConstants;
+        protected Constant[] keyConstants;
         private final LabelRef[] keyTargets;
         private LabelRef defaultTarget;
         @Alive({REG}) protected Value key;
@@ -408,9 +408,14 @@
         private final List<Label> conditionalLabels = new ArrayList<>();
 
         public StrategySwitchOp(Value constantTableBase, SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value scratch) {
-            super(TYPE);
+            this(TYPE, constantTableBase, strategy, keyTargets, defaultTarget, key, scratch);
+        }
+
+        protected StrategySwitchOp(LIRInstructionClass<? extends StrategySwitchOp> c, Value constantTableBase, SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Value key,
+                        Value scratch) {
+            super(c);
             this.strategy = strategy;
-            this.keyConstants = strategy.keyConstants;
+            this.keyConstants = strategy.getKeyConstants();
             this.keyTargets = keyTargets;
             this.defaultTarget = defaultTarget;
             this.constantTableBase = constantTableBase;
@@ -425,89 +430,103 @@
         public void emitCode(final CompilationResultBuilder crb, final SPARCMacroAssembler masm) {
             final Register keyRegister = asRegister(key);
             final Register constantBaseRegister = AllocatableValue.ILLEGAL.equals(constantTableBase) ? g0 : asRegister(constantTableBase);
-            BaseSwitchClosure closure = new BaseSwitchClosure(crb, masm, keyTargets, defaultTarget) {
-                int conditionalLabelPointer = 0;
-
-                /**
-                 * This method caches the generated labels over two assembly passes to get
-                 * information about branch lengths.
-                 */
-                @Override
-                public Label conditionalJump(int index, Condition condition) {
-                    Label label;
-                    if (conditionalLabelPointer <= conditionalLabels.size()) {
-                        label = new Label();
-                        conditionalLabels.add(label);
-                        conditionalLabelPointer = conditionalLabels.size();
-                    } else {
-                        // TODO: (sa) We rely here on the order how the labels are generated during
-                        // code generation; if the order is not stable ower two assembly passes, the
-                        // result can be wrong
-                        label = conditionalLabels.get(conditionalLabelPointer++);
-                    }
-                    conditionalJump(index, condition, label);
-                    return label;
-                }
-
-                @Override
-                protected void conditionalJump(int index, Condition condition, Label target) {
-                    JavaConstant constant = keyConstants[index];
-                    CC conditionCode;
-                    Long bits;
-                    switch (constant.getJavaKind()) {
-                        case Char:
-                        case Byte:
-                        case Short:
-                        case Int:
-                            conditionCode = CC.Icc;
-                            bits = constant.asLong();
-                            break;
-                        case Long: {
-                            conditionCode = CC.Xcc;
-                            bits = constant.asLong();
-                            break;
-                        }
-                        case Object: {
-                            conditionCode = crb.codeCache.getTarget().wordKind == JavaKind.Long ? CC.Xcc : CC.Icc;
-                            bits = constant.isDefaultForKind() ? 0L : null;
-                            break;
-                        }
-                        default:
-                            throw new JVMCIError("switch only supported for int, long and object");
-                    }
-                    ConditionFlag conditionFlag = fromCondition(conditionCode, condition, false);
-                    LabelHint hint = requestHint(masm, target);
-                    boolean isShortConstant = isSimm5(constant);
-                    int cbCondPosition = masm.position();
-                    if (!isShortConstant) { // Load constant takes one instruction
-                        cbCondPosition += SPARC.INSTRUCTION_SIZE;
-                    }
-                    boolean canUseShortBranch = masm.hasFeature(CPUFeature.CBCOND) && isShortBranch(masm, cbCondPosition, hint, target);
-                    if (bits != null && canUseShortBranch) {
-                        if (isShortConstant) {
-                            CBCOND.emit(masm, conditionFlag, conditionCode == Xcc, keyRegister, (int) (long) bits, target);
-                        } else {
-                            Register scratchRegister = asRegister(scratch);
-                            const2reg(crb, masm, scratch, constantBaseRegister, keyConstants[index], SPARCDelayedControlTransfer.DUMMY);
-                            CBCOND.emit(masm, conditionFlag, conditionCode == Xcc, keyRegister, scratchRegister, target);
-                        }
-                    } else {
-                        if (bits != null && isSimm13(constant)) {
-                            masm.cmp(keyRegister, (int) (long) bits); // Cast is safe
-                        } else {
-                            Register scratchRegister = asRegister(scratch);
-                            const2reg(crb, masm, scratch, constantBaseRegister, keyConstants[index], SPARCDelayedControlTransfer.DUMMY);
-                            masm.cmp(keyRegister, scratchRegister);
-                        }
-                        masm.bpcc(conditionFlag, ANNUL, target, conditionCode, PREDICT_TAKEN);
-                        masm.nop();  // delay slot
-                    }
-                }
-            };
-            strategy.run(closure);
+            strategy.run(new SwitchClosure(keyRegister, constantBaseRegister, crb, masm));
         }
 
-        private LabelHint requestHint(SPARCMacroAssembler masm, Label label) {
+        public class SwitchClosure extends BaseSwitchClosure {
+            private int conditionalLabelPointer = 0;
+
+            protected final Register keyRegister;
+            protected final Register constantBaseRegister;
+            protected final CompilationResultBuilder crb;
+            protected final SPARCMacroAssembler masm;
+
+            protected SwitchClosure(Register keyRegister, Register constantBaseRegister, CompilationResultBuilder crb, SPARCMacroAssembler masm) {
+                super(crb, masm, keyTargets, defaultTarget);
+                this.keyRegister = keyRegister;
+                this.constantBaseRegister = constantBaseRegister;
+                this.crb = crb;
+                this.masm = masm;
+            }
+
+            /**
+             * This method caches the generated labels over two assembly passes to get information
+             * about branch lengths.
+             */
+            @Override
+            public Label conditionalJump(int index, Condition condition) {
+                Label label;
+                if (conditionalLabelPointer <= conditionalLabels.size()) {
+                    label = new Label();
+                    conditionalLabels.add(label);
+                    conditionalLabelPointer = conditionalLabels.size();
+                } else {
+                    // TODO: (sa) We rely here on the order how the labels are generated during
+                    // code generation; if the order is not stable ower two assembly passes, the
+                    // result can be wrong
+                    label = conditionalLabels.get(conditionalLabelPointer++);
+                }
+                conditionalJump(index, condition, label);
+                return label;
+            }
+
+            @Override
+            protected void conditionalJump(int index, Condition condition, Label target) {
+                JavaConstant constant = (JavaConstant) keyConstants[index];
+                CC conditionCode;
+                Long bits;
+                switch (constant.getJavaKind()) {
+                    case Char:
+                    case Byte:
+                    case Short:
+                    case Int:
+                        conditionCode = CC.Icc;
+                        bits = constant.asLong();
+                        break;
+                    case Long: {
+                        conditionCode = CC.Xcc;
+                        bits = constant.asLong();
+                        break;
+                    }
+                    case Object: {
+                        conditionCode = crb.codeCache.getTarget().wordKind == JavaKind.Long ? CC.Xcc : CC.Icc;
+                        bits = constant.isDefaultForKind() ? 0L : null;
+                        break;
+                    }
+                    default:
+                        throw new JVMCIError("switch only supported for int, long and object");
+                }
+                ConditionFlag conditionFlag = fromCondition(conditionCode, condition, false);
+                LabelHint hint = requestHint(masm, target);
+                boolean isShortConstant = isSimm5(constant);
+                int cbCondPosition = masm.position();
+                if (!isShortConstant) { // Load constant takes one instruction
+                    cbCondPosition += SPARC.INSTRUCTION_SIZE;
+                }
+                boolean canUseShortBranch = masm.hasFeature(CPUFeature.CBCOND) && isShortBranch(masm, cbCondPosition, hint, target);
+                if (bits != null && canUseShortBranch) {
+                    if (isShortConstant) {
+                        CBCOND.emit(masm, conditionFlag, conditionCode == Xcc, keyRegister, (int) (long) bits, target);
+                    } else {
+                        Register scratchRegister = asRegister(scratch);
+                        const2reg(crb, masm, scratch, constantBaseRegister, (JavaConstant) keyConstants[index], SPARCDelayedControlTransfer.DUMMY);
+                        CBCOND.emit(masm, conditionFlag, conditionCode == Xcc, keyRegister, scratchRegister, target);
+                    }
+                } else {
+                    if (bits != null && isSimm13(constant)) {
+                        masm.cmp(keyRegister, (int) (long) bits); // Cast is safe
+                    } else {
+                        Register scratchRegister = asRegister(scratch);
+                        const2reg(crb, masm, scratch, constantBaseRegister, (JavaConstant) keyConstants[index], SPARCDelayedControlTransfer.DUMMY);
+                        masm.cmp(keyRegister, scratchRegister);
+                    }
+                    masm.bpcc(conditionFlag, ANNUL, target, conditionCode, PREDICT_TAKEN);
+                    masm.nop();  // delay slot
+                }
+            }
+        }
+
+        protected LabelHint requestHint(SPARCMacroAssembler masm, Label label) {
             LabelHint hint = labelHints.get(label);
             if (hint == null) {
                 hint = masm.requestLabelHint(label);
@@ -516,13 +535,20 @@
             return hint;
         }
 
+        protected int estimateEmbeddedSize(Constant c) {
+            JavaConstant v = (JavaConstant) c;
+            if (!SPARCAssembler.isSimm13(v)) {
+                return v.getJavaKind().getByteCount();
+            } else {
+                return 0;
+            }
+        }
+
         @Override
         public SizeEstimate estimateSize() {
             int constantBytes = 0;
-            for (JavaConstant v : keyConstants) {
-                if (!SPARCAssembler.isSimm13(v)) {
-                    constantBytes += v.getJavaKind().getByteCount();
-                }
+            for (Constant c : keyConstants) {
+                constantBytes += estimateEmbeddedSize(c);
             }
             return new SizeEstimate(4 * keyTargets.length, constantBytes);
         }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/SwitchStrategy.java	Sun Sep 13 21:03:52 2015 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/SwitchStrategy.java	Mon Sep 14 16:34:26 2015 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -151,8 +151,8 @@
 
         private int defaultEffort;
         private int defaultCount;
-        private final int[] keyEfforts = new int[keyConstants.length];
-        private final int[] keyCounts = new int[keyConstants.length];
+        private final int[] keyEfforts = new int[keyProbabilities.length];
+        private final int[] keyCounts = new int[keyProbabilities.length];
         private final LabelRef[] keyTargets;
 
         public EffortClosure(LabelRef[] keyTargets) {
@@ -183,7 +183,7 @@
         public double getAverageEffort() {
             double defaultProbability = 1;
             double effort = 0;
-            for (int i = 0; i < keyConstants.length; i++) {
+            for (int i = 0; i < keyProbabilities.length; i++) {
                 effort += keyEfforts[i] * keyProbabilities[i] / keyCounts[i];
                 defaultProbability -= keyProbabilities[i];
             }
@@ -192,34 +192,22 @@
     }
 
     public final double[] keyProbabilities;
-    public final JavaConstant[] keyConstants;
     private double averageEffort = -1;
     private EffortClosure effortClosure;
 
-    public SwitchStrategy(double[] keyProbabilities, JavaConstant[] keyConstants) {
-        assert keyConstants.length == keyProbabilities.length && keyConstants.length >= 2;
+    public SwitchStrategy(double[] keyProbabilities) {
+        assert keyProbabilities.length >= 2;
         this.keyProbabilities = keyProbabilities;
-        this.keyConstants = keyConstants;
     }
 
+    public abstract Constant[] getKeyConstants();
+
     public double getAverageEffort() {
         assert averageEffort >= 0 : "average effort was not calculated yet for this strategy";
         return averageEffort;
     }
 
     /**
-     * Looks for the end of a stretch of key constants that are successive numbers and have the same
-     * target.
-     */
-    protected int getSliceEnd(SwitchClosure closure, int pos) {
-        int slice = pos;
-        while (slice < (keyConstants.length - 1) && keyConstants[slice + 1].asLong() == keyConstants[slice].asLong() + 1 && closure.isSameTarget(slice, slice + 1)) {
-            slice++;
-        }
-        return slice;
-    }
-
-    /**
      * Tells the system that the given (inclusive) range of keys is reached after depth number of
      * comparisons, which is used to calculate the average effort.
      */
@@ -254,10 +242,13 @@
      */
     public static class SequentialStrategy extends SwitchStrategy {
         private final Integer[] indexes;
+        private final Constant[] keyConstants;
 
-        public SequentialStrategy(final double[] keyProbabilities, JavaConstant[] keyConstants) {
-            super(keyProbabilities, keyConstants);
+        public SequentialStrategy(final double[] keyProbabilities, Constant[] keyConstants) {
+            super(keyProbabilities);
+            assert keyProbabilities.length == keyConstants.length;
 
+            this.keyConstants = keyConstants;
             int keyCount = keyConstants.length;
             indexes = new Integer[keyCount];
             for (int i = 0; i < keyCount; i++) {
@@ -272,6 +263,11 @@
         }
 
         @Override
+        public Constant[] getKeyConstants() {
+            return keyConstants;
+        }
+
+        @Override
         public void run(SwitchClosure closure) {
             for (int i = 0; i < keyConstants.length - 1; i++) {
                 closure.conditionalJump(indexes[i], Condition.EQ, false);
@@ -284,10 +280,40 @@
     }
 
     /**
+     * Base class for strategies that rely on primitive integer keys.
+     */
+    private abstract static class PrimitiveStrategy extends SwitchStrategy {
+        protected final JavaConstant[] keyConstants;
+
+        protected PrimitiveStrategy(double[] keyProbabilities, JavaConstant[] keyConstants) {
+            super(keyProbabilities);
+            assert keyProbabilities.length == keyConstants.length;
+            this.keyConstants = keyConstants;
+        }
+
+        @Override
+        public JavaConstant[] getKeyConstants() {
+            return keyConstants;
+        }
+
+        /**
+         * Looks for the end of a stretch of key constants that are successive numbers and have the
+         * same target.
+         */
+        protected int getSliceEnd(SwitchClosure closure, int pos) {
+            int slice = pos;
+            while (slice < (keyConstants.length - 1) && keyConstants[slice + 1].asLong() == keyConstants[slice].asLong() + 1 && closure.isSameTarget(slice, slice + 1)) {
+                slice++;
+            }
+            return slice;
+        }
+    }
+
+    /**
      * This strategy divides the keys into ranges of successive keys with the same target and
      * creates comparisons for these ranges.
      */
-    public static class RangesStrategy extends SwitchStrategy {
+    public static class RangesStrategy extends PrimitiveStrategy {
         private final Integer[] indexes;
 
         public RangesStrategy(final double[] keyProbabilities, JavaConstant[] keyConstants) {
@@ -348,7 +374,7 @@
      * This strategy recursively subdivides the list of keys to create a binary search based on
      * probabilities.
      */
-    public static class BinaryStrategy extends SwitchStrategy {
+    public static class BinaryStrategy extends PrimitiveStrategy {
 
         private static final double MIN_PROBABILITY = 0.00001;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java	Sun Sep 13 21:03:52 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java	Mon Sep 14 16:34:26 2015 +0200
@@ -99,7 +99,7 @@
     /**
      * The key at the specified position, encoded in a Constant.
      */
-    public abstract JavaConstant keyAt(int i);
+    public abstract Constant keyAt(int i);
 
     public boolean structureEquals(SwitchNode switchNode) {
         return Arrays.equals(keySuccessors, switchNode.keySuccessors) && equalKeys(switchNode);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java	Sun Sep 13 21:03:52 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java	Mon Sep 14 16:34:26 2015 +0200
@@ -71,20 +71,7 @@
 
     @Override
     public boolean isSorted() {
-        JavaKind kind = value().getStackKind();
-        if (kind.isNumericInteger()) {
-            JavaConstant lastKey = null;
-            for (int i = 0; i < keyCount(); i++) {
-                JavaConstant key = keyAt(i);
-                if (lastKey != null && key.asLong() <= lastKey.asLong()) {
-                    return false;
-                }
-                lastKey = key;
-            }
-            return true;
-        } else {
-            return false;
-        }
+        return false;
     }
 
     @Override
@@ -93,8 +80,8 @@
     }
 
     @Override
-    public JavaConstant keyAt(int index) {
-        return (JavaConstant) keys[index].getObjectHub();
+    public Constant keyAt(int index) {
+        return keys[index].getObjectHub();
     }
 
     @Override
@@ -118,12 +105,11 @@
     @Override
     public void simplify(SimplifierTool tool) {
         if (value() instanceof ConstantNode) {
-            JavaConstant constant = value().asJavaConstant();
+            Constant constant = value().asConstant();
 
             int survivingEdge = keySuccessorIndex(keyCount());
             for (int i = 0; i < keyCount(); i++) {
-                JavaConstant typeHub = keyAt(i);
-                assert constant.getJavaKind() == typeHub.getJavaKind();
+                Constant typeHub = keyAt(i);
                 Boolean equal = tool.getConstantReflection().constantEquals(constant, typeHub);
                 if (equal == null) {
                     /* We don't know if this key is a match or not, so we cannot simplify. */