Mercurial > hg > graal-compiler
changeset 22623:ed489bbcccbb
Properly handle metaspace constants in switch statements.
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. */