# HG changeset patch # User Michael Van De Vanter # Date 1431479093 25200 # Node ID acfc5e32e6782ab3b32c2297258fcf0de9728a7d # Parent e34bc00733d19c7a83b307e83046bd11a50fbd27# Parent 6d5a198d23e67bb4b850ce1d74f5c338840cfe04 Merge with 6d5a198d23e67bb4b850ce1d74f5c338840cfe04 diff -r e34bc00733d1 -r acfc5e32e678 graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java --- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Tue May 12 17:29:49 2015 -0700 +++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Tue May 12 18:04:53 2015 -0700 @@ -52,15 +52,7 @@ import com.oracle.graal.lir.sparc.SPARCControlFlow.ReturnOp; import com.oracle.graal.lir.sparc.SPARCControlFlow.StrategySwitchOp; import com.oracle.graal.lir.sparc.SPARCControlFlow.TableSwitchOp; -import com.oracle.graal.lir.sparc.SPARCMove.LoadAddressOp; -import com.oracle.graal.lir.sparc.SPARCMove.LoadDataAddressOp; -import com.oracle.graal.lir.sparc.SPARCMove.MembarOp; -import com.oracle.graal.lir.sparc.SPARCMove.MoveFpGp; -import com.oracle.graal.lir.sparc.SPARCMove.MoveFpGpVIS3; -import com.oracle.graal.lir.sparc.SPARCMove.MoveFromRegOp; -import com.oracle.graal.lir.sparc.SPARCMove.MoveToRegOp; -import com.oracle.graal.lir.sparc.SPARCMove.SPARCStackMove; -import com.oracle.graal.lir.sparc.SPARCMove.StackLoadAddressOp; +import com.oracle.graal.lir.sparc.SPARCMove.*; import com.oracle.graal.phases.util.*; import com.oracle.graal.sparc.*; import com.oracle.graal.sparc.SPARC.CPUFeature; @@ -1074,4 +1066,11 @@ append(new ReturnOp(Value.ILLEGAL)); } + public Value emitSignExtendLoad(LIRKind kind, Value address, LIRFrameState state) { + SPARCAddressValue loadAddress = asAddressValue(address); + Variable result = newVariable(kind); + append(new LoadOp((Kind) kind.getPlatformKind(), result, loadAddress, state, true)); + return result; + } + } diff -r e34bc00733d1 -r acfc5e32e678 graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCNodeLIRBuilder.java --- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCNodeLIRBuilder.java Tue May 12 17:29:49 2015 -0700 +++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCNodeLIRBuilder.java Tue May 12 18:04:53 2015 -0700 @@ -29,7 +29,7 @@ import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.match.*; import com.oracle.graal.lir.*; -import com.oracle.graal.lir.StandardOp.*; +import com.oracle.graal.lir.StandardOp.JumpOp; import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.sparc.*; import com.oracle.graal.nodes.*; @@ -106,7 +106,7 @@ Kind localToKind = toKind; return builder -> { Value address = access.accessLocation().generateAddress(builder, gen, operand(access.object())); - Value v = getLIRGeneratorTool().emitLoad(LIRKind.value(localFromKind), address, getState(access)); + Value v = getLIRGeneratorTool().emitSignExtendLoad(LIRKind.value(localFromKind), address, getState(access)); return getLIRGeneratorTool().emitReinterpret(LIRKind.value(localToKind), v); }; } @@ -116,4 +116,9 @@ public ComplexMatchResult signExtend(SignExtendNode root, Access access) { return emitSignExtendMemory(access, root.getInputBits(), root.getResultBits()); } + + @Override + public SPARCLIRGenerator getLIRGeneratorTool() { + return (SPARCLIRGenerator) super.getLIRGeneratorTool(); + } } diff -r e34bc00733d1 -r acfc5e32e678 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotMove.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotMove.java Tue May 12 17:29:49 2015 -0700 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotMove.java Tue May 12 18:04:53 2015 -0700 @@ -28,26 +28,29 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; +import com.oracle.graal.asm.sparc.*; import com.oracle.graal.asm.sparc.SPARCAssembler.Annul; import com.oracle.graal.asm.sparc.SPARCAssembler.BranchPredict; import com.oracle.graal.asm.sparc.SPARCAssembler.CC; import com.oracle.graal.asm.sparc.SPARCAssembler.ConditionFlag; import com.oracle.graal.asm.sparc.SPARCAssembler.RCondition; -import com.oracle.graal.asm.sparc.*; +import com.oracle.graal.asm.sparc.SPARCMacroAssembler.ScratchRegister; import com.oracle.graal.compiler.common.*; +import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.HotSpotVMConfig.CompressEncoding; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.MoveOp; import com.oracle.graal.lir.asm.*; import com.oracle.graal.lir.sparc.*; +import com.oracle.graal.sparc.*; public class SPARCHotSpotMove { public static final class HotSpotLoadConstantOp extends SPARCLIRInstruction implements MoveOp { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(HotSpotLoadConstantOp.class); - @Def({REG}) private AllocatableValue result; + @Def({REG, STACK}) private AllocatableValue result; private final JavaConstant input; public HotSpotLoadConstantOp(AllocatableValue result, JavaConstant input) { @@ -58,43 +61,74 @@ @Override public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { - assert isRegister(result); - if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(input)) { - masm.mov(0, asRegister(result)); - } else if (input instanceof HotSpotObjectConstant) { - boolean compressed = ((HotSpotObjectConstant) input).isCompressed(); + if (isStackSlot(result)) { + StackSlot ss = asStackSlot(result); + try (ScratchRegister s1 = masm.getScratchRegister()) { + Register sr1 = s1.getRegister(); + loadToRegister(crb, masm, sr1.asValue(), input); + try (ScratchRegister s2 = masm.getScratchRegister()) { + Register sr2 = s2.getRegister(); + int stackBias = HotSpotGraalRuntime.runtime().getConfig().stackBias; + int offset = crb.frameMap.offsetForStackSlot(ss); + new SPARCMacroAssembler.Setx(offset + stackBias, sr2).emit(masm); + SPARCAddress addr = new SPARCAddress(SPARC.sp, sr2); + Kind resultKind = (Kind) result.getPlatformKind(); + switch (resultKind) { + case Int: + masm.stw(sr1, addr); + break; + case Long: + case Object: + masm.stx(sr1, addr); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + } + } else { + loadToRegister(crb, masm, result, input); + } + } + + private static void loadToRegister(CompilationResultBuilder crb, SPARCMacroAssembler masm, AllocatableValue dest, JavaConstant constant) { + assert isRegister(dest); + if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(constant)) { + masm.mov(0, asRegister(dest)); + } else if (constant instanceof HotSpotObjectConstant) { + boolean compressed = ((HotSpotObjectConstant) constant).isCompressed(); if (crb.target.inlineObjects) { - crb.recordInlineDataInCode(input); + crb.recordInlineDataInCode(constant); if (compressed) { - masm.sethi(0xDEADDEAD >>> 10, asRegister(result)); - masm.add(asRegister(result), 0xAD & 0x3F, asRegister(result)); + masm.sethi(0xDEADDEAD >>> 10, asRegister(dest)); + masm.add(asRegister(dest), 0xAD & 0x3F, asRegister(dest)); } else { - new SPARCMacroAssembler.Setx(0xDEADDEADDEADDEADL, asRegister(result), true).emit(masm); + new SPARCMacroAssembler.Setx(0xDEADDEADDEADDEADL, asRegister(dest), true).emit(masm); } } else { GraalInternalError.unimplemented(); } - } else if (input instanceof HotSpotMetaspaceConstant) { - assert input.getKind() == Kind.Int || input.getKind() == Kind.Long; - boolean compressed = input.getKind() == Kind.Int; + } else if (constant instanceof HotSpotMetaspaceConstant) { + assert constant.getKind() == Kind.Int || constant.getKind() == Kind.Long; + boolean compressed = constant.getKind() == Kind.Int; boolean isImmutable = GraalOptions.ImmutableCode.getValue(); boolean generatePIC = GraalOptions.GeneratePIC.getValue(); - crb.recordInlineDataInCode(input); + crb.recordInlineDataInCode(constant); if (compressed) { if (isImmutable && generatePIC) { GraalInternalError.unimplemented(); } else { - new SPARCMacroAssembler.Setx(input.asInt(), asRegister(result), true).emit(masm); + new SPARCMacroAssembler.Setx(constant.asInt(), asRegister(dest), true).emit(masm); } } else { if (isImmutable && generatePIC) { GraalInternalError.unimplemented(); } else { - new SPARCMacroAssembler.Setx(input.asLong(), asRegister(result), true).emit(masm); + new SPARCMacroAssembler.Setx(constant.asLong(), asRegister(dest), true).emit(masm); } } } else { - SPARCMove.move(crb, masm, result, input, SPARCDelayedControlTransfer.DUMMY); + SPARCMove.move(crb, masm, dest, constant, SPARCDelayedControlTransfer.DUMMY); } } @@ -171,8 +205,7 @@ Register resReg = asRegister(result); if (encoding.shift != 0) { - masm.sllx(resReg, 32, resReg); - masm.srlx(resReg, 32 - encoding.shift, resReg); + masm.sll(resReg, encoding.shift, resReg); } if (encoding.base != 0) { diff -r e34bc00733d1 -r acfc5e32e678 graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java Tue May 12 17:29:49 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1260 +0,0 @@ -/* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.java; - -import static com.oracle.graal.api.code.TypeCheckHints.*; -import static com.oracle.graal.api.meta.DeoptimizationReason.*; -import static com.oracle.graal.bytecode.Bytecodes.*; -import static com.oracle.graal.java.AbstractBytecodeParser.Options.*; - -import java.util.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.bytecode.*; -import com.oracle.graal.compiler.common.*; -import com.oracle.graal.compiler.common.calc.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.graphbuilderconf.*; -import com.oracle.graal.java.BciBlockMapping.BciBlock; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; -import com.oracle.graal.options.*; -import com.oracle.graal.phases.*; - -public abstract class AbstractBytecodeParser { - - public static class Options { - // @formatter:off - @Option(help = "The trace level for the bytecode parser used when building a graph from bytecode", type = OptionType.Debug) - public static final OptionValue TraceBytecodeParserLevel = new OptionValue<>(0); - - @Option(help = "Inlines trivial methods during bytecode parsing.", type = OptionType.Expert) - public static final StableOptionValue InlineDuringParsing = new StableOptionValue<>(false); - - @Option(help = "Inlines intrinsic methods during bytecode parsing.", type = OptionType.Expert) - public static final StableOptionValue InlineIntrinsicsDuringParsing = new StableOptionValue<>(true); - - @Option(help = "Traces inlining performed during bytecode parsing.", type = OptionType.Debug) - public static final StableOptionValue TraceInlineDuringParsing = new StableOptionValue<>(false); - - @Option(help = "Traces use of plugins during bytecode parsing.", type = OptionType.Debug) - public static final StableOptionValue TraceParserPlugins = new StableOptionValue<>(false); - - @Option(help = "Maximum depth when inlining during bytecode parsing.", type = OptionType.Debug) - public static final StableOptionValue InlineDuringParsingMaxDepth = new StableOptionValue<>(10); - - @Option(help = "Dump graphs after non-trivial changes during bytecode parsing.", type = OptionType.Debug) - public static final StableOptionValue DumpDuringGraphBuilding = new StableOptionValue<>(false); - - @Option(help = "Max number of loop explosions per method.", type = OptionType.Debug) - public static final OptionValue MaximumLoopExplosionCount = new OptionValue<>(10000); - - @Option(help = "Do not bail out but throw an exception on failed loop explosion.", type = OptionType.Debug) - public static final OptionValue FailedLoopExplosionIsFatal = new OptionValue<>(false); - - @Option(help = "When creating info points hide the methods of the substitutions.", type = OptionType.Debug) - public static final OptionValue HideSubstitutionStates = new OptionValue<>(false); - - // @formatter:on - } - - /** - * The minimum value to which {@link Options#TraceBytecodeParserLevel} must be set to trace the - * bytecode instructions as they are parsed. - */ - public static final int TRACELEVEL_INSTRUCTIONS = 1; - - /** - * The minimum value to which {@link Options#TraceBytecodeParserLevel} must be set to trace the - * frame state before each bytecode instruction as it is parsed. - */ - public static final int TRACELEVEL_STATE = 2; - - protected HIRFrameStateBuilder frameState; - protected BciBlock currentBlock; - - protected final BytecodeStream stream; - protected final GraphBuilderConfiguration graphBuilderConfig; - protected final ResolvedJavaMethod method; - protected final ProfilingInfo profilingInfo; - protected final OptimisticOptimizations optimisticOpts; - protected final ConstantPool constantPool; - protected final MetaAccessProvider metaAccess; - - protected final IntrinsicContext intrinsicContext; - - /** - * Meters the number of actual bytecodes parsed. - */ - public static final DebugMetric BytecodesParsed = Debug.metric("BytecodesParsed"); - - public AbstractBytecodeParser(MetaAccessProvider metaAccess, ResolvedJavaMethod method, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, - IntrinsicContext intrinsicContext) { - this.graphBuilderConfig = graphBuilderConfig; - this.optimisticOpts = optimisticOpts; - this.metaAccess = metaAccess; - this.stream = new BytecodeStream(method.getCode()); - this.profilingInfo = (graphBuilderConfig.getUseProfiling() ? method.getProfilingInfo() : null); - this.constantPool = method.getConstantPool(); - this.method = method; - this.intrinsicContext = intrinsicContext; - assert metaAccess != null; - } - - public void setCurrentFrameState(HIRFrameStateBuilder frameState) { - this.frameState = frameState; - } - - protected final BytecodeStream getStream() { - return stream; - } - - public int bci() { - return stream.currentBCI(); - } - - public void loadLocal(int index, Kind kind) { - frameState.push(kind, frameState.loadLocal(index)); - } - - public void storeLocal(Kind kind, int index) { - ValueNode value; - if (kind == Kind.Object) { - value = frameState.xpop(); - // astore and astore_ may be used to store a returnAddress (jsr) - assert parsingIntrinsic() || (value.getKind() == Kind.Object || value.getKind() == Kind.Int) : value + ":" + value.getKind(); - } else { - value = frameState.pop(kind); - } - frameState.storeLocal(index, value, kind); - } - - /** - * @param type the unresolved type of the constant - */ - protected abstract void handleUnresolvedLoadConstant(JavaType type); - - /** - * @param type the unresolved type of the type check - * @param object the object value whose type is being checked against {@code type} - */ - protected abstract void handleUnresolvedCheckCast(JavaType type, ValueNode object); - - /** - * @param type the unresolved type of the type check - * @param object the object value whose type is being checked against {@code type} - */ - protected abstract void handleUnresolvedInstanceOf(JavaType type, ValueNode object); - - /** - * @param type the type being instantiated - */ - protected abstract void handleUnresolvedNewInstance(JavaType type); - - /** - * @param type the type of the array being instantiated - * @param length the length of the array - */ - protected abstract void handleUnresolvedNewObjectArray(JavaType type, ValueNode length); - - /** - * @param type the type being instantiated - * @param dims the dimensions for the multi-array - */ - protected abstract void handleUnresolvedNewMultiArray(JavaType type, List dims); - - /** - * @param field the unresolved field - * @param receiver the object containing the field or {@code null} if {@code field} is static - */ - protected abstract void handleUnresolvedLoadField(JavaField field, ValueNode receiver); - - /** - * @param field the unresolved field - * @param value the value being stored to the field - * @param receiver the object containing the field or {@code null} if {@code field} is static - */ - protected abstract void handleUnresolvedStoreField(JavaField field, ValueNode value, ValueNode receiver); - - /** - * @param type - */ - protected abstract void handleUnresolvedExceptionType(JavaType type); - - // protected abstract void handleUnresolvedInvoke(JavaMethod javaMethod, InvokeKind invokeKind); - - // protected abstract DispatchBeginNode handleException(ValueNode exceptionObject, int bci); - - private void genLoadConstant(int cpi, int opcode) { - Object con = lookupConstant(cpi, opcode); - - if (con instanceof JavaType) { - // this is a load of class constant which might be unresolved - JavaType type = (JavaType) con; - if (type instanceof ResolvedJavaType) { - frameState.push(Kind.Object, appendConstant(((ResolvedJavaType) type).getJavaClass())); - } else { - handleUnresolvedLoadConstant(type); - } - } else if (con instanceof JavaConstant) { - JavaConstant constant = (JavaConstant) con; - frameState.push(constant.getKind().getStackKind(), appendConstant(constant)); - } else { - throw new Error("lookupConstant returned an object of incorrect type"); - } - } - - protected abstract ValueNode genLoadIndexed(ValueNode index, ValueNode array, Kind kind); - - private void genLoadIndexed(Kind kind) { - ValueNode index = frameState.ipop(); - ValueNode array = emitExplicitExceptions(frameState.apop(), index); - if (!tryLoadIndexedPlugin(kind, index, array)) { - frameState.push(kind.getStackKind(), append(genLoadIndexed(array, index, kind))); - } - } - - protected abstract void traceWithContext(String format, Object... args); - - protected boolean tryLoadIndexedPlugin(Kind kind, ValueNode index, ValueNode array) { - LoadIndexedPlugin loadIndexedPlugin = graphBuilderConfig.getPlugins().getLoadIndexedPlugin(); - if (loadIndexedPlugin != null && loadIndexedPlugin.apply((GraphBuilderContext) this, array, index, kind)) { - if (TraceParserPlugins.getValue()) { - traceWithContext("used load indexed plugin"); - } - return true; - } else { - return false; - } - } - - protected abstract void genStoreIndexed(ValueNode array, ValueNode index, Kind kind, ValueNode value); - - private void genStoreIndexed(Kind kind) { - ValueNode value = frameState.pop(kind.getStackKind()); - ValueNode index = frameState.ipop(); - ValueNode array = emitExplicitExceptions(frameState.apop(), index); - genStoreIndexed(array, index, kind, value); - } - - private void stackOp(int opcode) { - switch (opcode) { - case DUP_X1: { - ValueNode w1 = frameState.xpop(); - ValueNode w2 = frameState.xpop(); - frameState.xpush(w1); - frameState.xpush(w2); - frameState.xpush(w1); - break; - } - case DUP_X2: { - ValueNode w1 = frameState.xpop(); - ValueNode w2 = frameState.xpop(); - ValueNode w3 = frameState.xpop(); - frameState.xpush(w1); - frameState.xpush(w3); - frameState.xpush(w2); - frameState.xpush(w1); - break; - } - case DUP2: { - ValueNode w1 = frameState.xpop(); - ValueNode w2 = frameState.xpop(); - frameState.xpush(w2); - frameState.xpush(w1); - frameState.xpush(w2); - frameState.xpush(w1); - break; - } - case DUP2_X1: { - ValueNode w1 = frameState.xpop(); - ValueNode w2 = frameState.xpop(); - ValueNode w3 = frameState.xpop(); - frameState.xpush(w2); - frameState.xpush(w1); - frameState.xpush(w3); - frameState.xpush(w2); - frameState.xpush(w1); - break; - } - case DUP2_X2: { - ValueNode w1 = frameState.xpop(); - ValueNode w2 = frameState.xpop(); - ValueNode w3 = frameState.xpop(); - ValueNode w4 = frameState.xpop(); - frameState.xpush(w2); - frameState.xpush(w1); - frameState.xpush(w4); - frameState.xpush(w3); - frameState.xpush(w2); - frameState.xpush(w1); - break; - } - case SWAP: { - ValueNode w1 = frameState.xpop(); - ValueNode w2 = frameState.xpop(); - frameState.xpush(w1); - frameState.xpush(w2); - break; - } - default: - throw GraalInternalError.shouldNotReachHere(); - } - } - - protected abstract ValueNode genIntegerAdd(Kind kind, ValueNode x, ValueNode y); - - protected abstract ValueNode genIntegerSub(Kind kind, ValueNode x, ValueNode y); - - protected abstract ValueNode genIntegerMul(Kind kind, ValueNode x, ValueNode y); - - protected abstract ValueNode genFloatAdd(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP); - - protected abstract ValueNode genFloatSub(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP); - - protected abstract ValueNode genFloatMul(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP); - - protected abstract ValueNode genFloatDiv(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP); - - protected abstract ValueNode genFloatRem(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP); - - private void genArithmeticOp(Kind result, int opcode) { - ValueNode y = frameState.pop(result); - ValueNode x = frameState.pop(result); - boolean isStrictFP = method.isStrict(); - ValueNode v; - switch (opcode) { - case IADD: - case LADD: - v = genIntegerAdd(result, x, y); - break; - case FADD: - case DADD: - v = genFloatAdd(result, x, y, isStrictFP); - break; - case ISUB: - case LSUB: - v = genIntegerSub(result, x, y); - break; - case FSUB: - case DSUB: - v = genFloatSub(result, x, y, isStrictFP); - break; - case IMUL: - case LMUL: - v = genIntegerMul(result, x, y); - break; - case FMUL: - case DMUL: - v = genFloatMul(result, x, y, isStrictFP); - break; - case FDIV: - case DDIV: - v = genFloatDiv(result, x, y, isStrictFP); - break; - case FREM: - case DREM: - v = genFloatRem(result, x, y, isStrictFP); - break; - default: - throw new GraalInternalError("should not reach"); - } - frameState.push(result, append(v)); - } - - protected abstract ValueNode genIntegerDiv(Kind kind, ValueNode x, ValueNode y); - - protected abstract ValueNode genIntegerRem(Kind kind, ValueNode x, ValueNode y); - - private void genIntegerDivOp(Kind result, int opcode) { - ValueNode y = frameState.pop(result); - ValueNode x = frameState.pop(result); - ValueNode v; - switch (opcode) { - case IDIV: - case LDIV: - v = genIntegerDiv(result, x, y); - break; - case IREM: - case LREM: - v = genIntegerRem(result, x, y); - break; - default: - throw new GraalInternalError("should not reach"); - } - frameState.push(result, append(v)); - } - - protected abstract ValueNode genNegateOp(ValueNode x); - - private void genNegateOp(Kind kind) { - frameState.push(kind, append(genNegateOp(frameState.pop(kind)))); - } - - protected abstract ValueNode genLeftShift(Kind kind, ValueNode x, ValueNode y); - - protected abstract ValueNode genRightShift(Kind kind, ValueNode x, ValueNode y); - - protected abstract ValueNode genUnsignedRightShift(Kind kind, ValueNode x, ValueNode y); - - private void genShiftOp(Kind kind, int opcode) { - ValueNode s = frameState.ipop(); - ValueNode x = frameState.pop(kind); - ValueNode v; - switch (opcode) { - case ISHL: - case LSHL: - v = genLeftShift(kind, x, s); - break; - case ISHR: - case LSHR: - v = genRightShift(kind, x, s); - break; - case IUSHR: - case LUSHR: - v = genUnsignedRightShift(kind, x, s); - break; - default: - throw new GraalInternalError("should not reach"); - } - frameState.push(kind, append(v)); - } - - protected abstract ValueNode genAnd(Kind kind, ValueNode x, ValueNode y); - - protected abstract ValueNode genOr(Kind kind, ValueNode x, ValueNode y); - - protected abstract ValueNode genXor(Kind kind, ValueNode x, ValueNode y); - - private void genLogicOp(Kind kind, int opcode) { - ValueNode y = frameState.pop(kind); - ValueNode x = frameState.pop(kind); - ValueNode v; - switch (opcode) { - case IAND: - case LAND: - v = genAnd(kind, x, y); - break; - case IOR: - case LOR: - v = genOr(kind, x, y); - break; - case IXOR: - case LXOR: - v = genXor(kind, x, y); - break; - default: - throw new GraalInternalError("should not reach"); - } - frameState.push(kind, append(v)); - } - - protected abstract ValueNode genNormalizeCompare(ValueNode x, ValueNode y, boolean isUnorderedLess); - - private void genCompareOp(Kind kind, boolean isUnorderedLess) { - ValueNode y = frameState.pop(kind); - ValueNode x = frameState.pop(kind); - frameState.ipush(append(genNormalizeCompare(x, y, isUnorderedLess))); - } - - protected abstract ValueNode genFloatConvert(FloatConvert op, ValueNode input); - - private void genFloatConvert(FloatConvert op, Kind from, Kind to) { - ValueNode input = frameState.pop(from.getStackKind()); - frameState.push(to.getStackKind(), append(genFloatConvert(op, input))); - } - - protected abstract ValueNode genNarrow(ValueNode input, int bitCount); - - protected abstract ValueNode genSignExtend(ValueNode input, int bitCount); - - protected abstract ValueNode genZeroExtend(ValueNode input, int bitCount); - - private void genSignExtend(Kind from, Kind to) { - ValueNode input = frameState.pop(from.getStackKind()); - if (from != from.getStackKind()) { - input = append(genNarrow(input, from.getBitCount())); - } - frameState.push(to.getStackKind(), append(genSignExtend(input, to.getBitCount()))); - } - - private void genZeroExtend(Kind from, Kind to) { - ValueNode input = frameState.pop(from.getStackKind()); - if (from != from.getStackKind()) { - input = append(genNarrow(input, from.getBitCount())); - } - frameState.push(to.getStackKind(), append(genZeroExtend(input, to.getBitCount()))); - } - - private void genNarrow(Kind from, Kind to) { - ValueNode input = frameState.pop(from.getStackKind()); - frameState.push(to.getStackKind(), append(genNarrow(input, to.getBitCount()))); - } - - private void genIncrement() { - int index = getStream().readLocalIndex(); - int delta = getStream().readIncrement(); - ValueNode x = frameState.loadLocal(index); - ValueNode y = appendConstant(JavaConstant.forInt(delta)); - frameState.storeLocal(index, append(genIntegerAdd(Kind.Int, x, y))); - } - - protected abstract void genGoto(); - - protected abstract ValueNode genObjectEquals(ValueNode x, ValueNode y); - - protected abstract ValueNode genIntegerEquals(ValueNode x, ValueNode y); - - protected abstract ValueNode genIntegerLessThan(ValueNode x, ValueNode y); - - protected abstract ValueNode genUnique(ValueNode x); - - protected abstract void genIf(ValueNode x, Condition cond, ValueNode y); - - private void genIfZero(Condition cond) { - ValueNode y = appendConstant(JavaConstant.INT_0); - ValueNode x = frameState.ipop(); - genIf(x, cond, y); - } - - private void genIfNull(Condition cond) { - ValueNode y = appendConstant(JavaConstant.NULL_POINTER); - ValueNode x = frameState.apop(); - genIf(x, cond, y); - } - - private void genIfSame(Kind kind, Condition cond) { - ValueNode y = frameState.pop(kind); - ValueNode x = frameState.pop(kind); - genIf(x, cond, y); - } - - protected abstract void genThrow(); - - protected JavaType lookupType(int cpi, int bytecode) { - maybeEagerlyResolve(cpi, bytecode); - JavaType result = constantPool.lookupType(cpi, bytecode); - assert !graphBuilderConfig.unresolvedIsError() || result instanceof ResolvedJavaType; - return result; - } - - private JavaMethod lookupMethod(int cpi, int opcode) { - maybeEagerlyResolve(cpi, opcode); - JavaMethod result = constantPool.lookupMethod(cpi, opcode); - /* - * In general, one cannot assume that the declaring class being initialized is useful, since - * the actual concrete receiver may be a different class (except for static calls). Also, - * interfaces are initialized only under special circumstances, so that this assertion would - * often fail for interface calls. - */ - assert !graphBuilderConfig.unresolvedIsError() || (result instanceof ResolvedJavaMethod && (opcode != INVOKESTATIC || ((ResolvedJavaMethod) result).getDeclaringClass().isInitialized())) : result; - return result; - } - - private JavaField lookupField(int cpi, int opcode) { - maybeEagerlyResolve(cpi, opcode); - JavaField result = constantPool.lookupField(cpi, opcode); - assert !graphBuilderConfig.unresolvedIsError() || (result instanceof ResolvedJavaField && ((ResolvedJavaField) result).getDeclaringClass().isInitialized()) : result; - return result; - } - - private Object lookupConstant(int cpi, int opcode) { - maybeEagerlyResolve(cpi, opcode); - Object result = constantPool.lookupConstant(cpi); - assert !graphBuilderConfig.eagerResolving() || !(result instanceof JavaType) || (result instanceof ResolvedJavaType) : result; - return result; - } - - private void maybeEagerlyResolve(int cpi, int bytecode) { - if (graphBuilderConfig.eagerResolving() || intrinsicContext != null) { - constantPool.loadReferencedType(cpi, bytecode); - } - } - - private JavaTypeProfile getProfileForTypeCheck(ResolvedJavaType type) { - if (parsingIntrinsic() || profilingInfo == null || !optimisticOpts.useTypeCheckHints() || !canHaveSubtype(type)) { - return null; - } else { - return profilingInfo.getTypeProfile(bci()); - } - } - - protected abstract ValueNode createCheckCast(ResolvedJavaType type, ValueNode object, JavaTypeProfile profileForTypeCheck, boolean forStoreCheck); - - private void genCheckCast() { - int cpi = getStream().readCPI(); - JavaType type = lookupType(cpi, CHECKCAST); - ValueNode object = frameState.apop(); - if (type instanceof ResolvedJavaType) { - ResolvedJavaType resolvedType = (ResolvedJavaType) type; - JavaTypeProfile profile = getProfileForTypeCheck(resolvedType); - TypeCheckPlugin typeCheckPlugin = this.graphBuilderConfig.getPlugins().getTypeCheckPlugin(); - if (typeCheckPlugin == null || !typeCheckPlugin.checkCast((GraphBuilderContext) this, object, resolvedType, profile)) { - ValueNode checkCastNode = append(createCheckCast(resolvedType, object, profile, false)); - frameState.apush(checkCastNode); - } - } else { - handleUnresolvedCheckCast(type, object); - } - } - - protected abstract ValueNode createInstanceOf(ResolvedJavaType type, ValueNode object, JavaTypeProfile profileForTypeCheck); - - protected abstract ValueNode genConditional(ValueNode x); - - private void genInstanceOf() { - int cpi = getStream().readCPI(); - JavaType type = lookupType(cpi, INSTANCEOF); - ValueNode object = frameState.apop(); - if (type instanceof ResolvedJavaType) { - ResolvedJavaType resolvedType = (ResolvedJavaType) type; - JavaTypeProfile profile = getProfileForTypeCheck(resolvedType); - TypeCheckPlugin typeCheckPlugin = this.graphBuilderConfig.getPlugins().getTypeCheckPlugin(); - if (typeCheckPlugin == null || !typeCheckPlugin.instanceOf((GraphBuilderContext) this, object, resolvedType, profile)) { - ValueNode instanceOfNode = createInstanceOf(resolvedType, object, profile); - frameState.ipush(append(genConditional(genUnique(instanceOfNode)))); - } - } else { - handleUnresolvedInstanceOf(type, object); - } - } - - protected abstract ValueNode createNewInstance(ResolvedJavaType type, boolean fillContents); - - void genNewInstance(int cpi) { - JavaType type = lookupType(cpi, NEW); - if (type instanceof ResolvedJavaType && ((ResolvedJavaType) type).isInitialized()) { - ResolvedJavaType[] skippedExceptionTypes = this.graphBuilderConfig.getSkippedExceptionTypes(); - if (skippedExceptionTypes != null) { - for (ResolvedJavaType exceptionType : skippedExceptionTypes) { - if (exceptionType.isAssignableFrom((ResolvedJavaType) type)) { - append(new DeoptimizeNode(DeoptimizationAction.None, TransferToInterpreter)); - return; - } - } - } - frameState.apush(append(createNewInstance((ResolvedJavaType) type, true))); - } else { - handleUnresolvedNewInstance(type); - } - } - - /** - * Gets the kind of array elements for the array type code that appears in a - * {@link Bytecodes#NEWARRAY} bytecode. - * - * @param code the array type code - * @return the kind from the array type code - */ - public static Class arrayTypeCodeToClass(int code) { - // Checkstyle: stop - switch (code) { - case 4: - return boolean.class; - case 5: - return char.class; - case 6: - return float.class; - case 7: - return double.class; - case 8: - return byte.class; - case 9: - return short.class; - case 10: - return int.class; - case 11: - return long.class; - default: - throw new IllegalArgumentException("unknown array type code: " + code); - } - // Checkstyle: resume - } - - private void genNewPrimitiveArray(int typeCode) { - Class clazz = arrayTypeCodeToClass(typeCode); - ResolvedJavaType elementType = metaAccess.lookupJavaType(clazz); - frameState.apush(append(createNewArray(elementType, frameState.ipop(), true))); - } - - private void genNewObjectArray(int cpi) { - JavaType type = lookupType(cpi, ANEWARRAY); - ValueNode length = frameState.ipop(); - if (type instanceof ResolvedJavaType) { - frameState.apush(append(createNewArray((ResolvedJavaType) type, length, true))); - } else { - handleUnresolvedNewObjectArray(type, length); - } - - } - - protected abstract ValueNode createNewArray(ResolvedJavaType elementType, ValueNode length, boolean fillContents); - - private void genNewMultiArray(int cpi) { - JavaType type = lookupType(cpi, MULTIANEWARRAY); - int rank = getStream().readUByte(bci() + 3); - List dims = new ArrayList<>(Collections.nCopies(rank, null)); - for (int i = rank - 1; i >= 0; i--) { - dims.set(i, frameState.ipop()); - } - if (type instanceof ResolvedJavaType) { - frameState.apush(append(createNewMultiArray((ResolvedJavaType) type, dims))); - } else { - handleUnresolvedNewMultiArray(type, dims); - } - } - - protected abstract ValueNode createNewMultiArray(ResolvedJavaType type, List dims); - - protected abstract ValueNode genLoadField(ValueNode receiver, ResolvedJavaField field); - - private void genGetField(JavaField field) { - Kind kind = field.getKind(); - ValueNode receiver = emitExplicitExceptions(frameState.apop(), null); - if ((field instanceof ResolvedJavaField) && ((ResolvedJavaField) field).getDeclaringClass().isInitialized()) { - LoadFieldPlugin loadFieldPlugin = this.graphBuilderConfig.getPlugins().getLoadFieldPlugin(); - if (loadFieldPlugin == null || !loadFieldPlugin.apply((GraphBuilderContext) this, receiver, (ResolvedJavaField) field)) { - appendOptimizedLoadField(kind, genLoadField(receiver, (ResolvedJavaField) field)); - } - } else { - handleUnresolvedLoadField(field, receiver); - } - } - - /** - * Emits control flow to null check a receiver if it's stamp does not indicate it is - * {@linkplain StampTool#isPointerNonNull always non-null}. - * - * @return the receiver with a stamp indicating non-nullness - */ - protected abstract ValueNode emitExplicitNullCheck(ValueNode receiver); - - /** - * Emits control flow to check an array index is within bounds of an array's length. - * - * @param index the index to check - * @param length the length of the array being indexed - */ - protected abstract void emitExplicitBoundsCheck(ValueNode index, ValueNode length); - - private static final DebugMetric EXPLICIT_EXCEPTIONS = Debug.metric("ExplicitExceptions"); - - protected abstract ValueNode genArrayLength(ValueNode x); - - /** - * @param receiver the receiver of an object based operation - * @param index the index of an array based operation that is to be tested for out of bounds. - * This is null for a non-array operation. - * @return the receiver value possibly modified to have a tighter stamp - */ - protected ValueNode emitExplicitExceptions(ValueNode receiver, ValueNode index) { - assert receiver != null; - if (graphBuilderConfig.omitAllExceptionEdges() || profilingInfo == null || - (optimisticOpts.useExceptionProbabilityForOperations() && profilingInfo.getExceptionSeen(bci()) == TriState.FALSE && !GraalOptions.StressExplicitExceptionCode.getValue())) { - return receiver; - } - - ValueNode nonNullReceiver = emitExplicitNullCheck(receiver); - if (index != null) { - ValueNode length = append(genArrayLength(nonNullReceiver)); - emitExplicitBoundsCheck(index, length); - } - EXPLICIT_EXCEPTIONS.increment(); - return nonNullReceiver; - } - - protected abstract void genStoreField(ValueNode receiver, ResolvedJavaField field, ValueNode value); - - private void genPutField(JavaField field) { - ValueNode value = frameState.pop(field.getKind().getStackKind()); - ValueNode receiver = emitExplicitExceptions(frameState.apop(), null); - if (field instanceof ResolvedJavaField && ((ResolvedJavaField) field).getDeclaringClass().isInitialized()) { - genStoreField(receiver, (ResolvedJavaField) field, value); - } else { - handleUnresolvedStoreField(field, value, receiver); - } - } - - private void genGetStatic(JavaField field) { - Kind kind = field.getKind(); - if (field instanceof ResolvedJavaField && ((ResolvedJavaType) field.getDeclaringClass()).isInitialized()) { - LoadFieldPlugin loadFieldPlugin = this.graphBuilderConfig.getPlugins().getLoadFieldPlugin(); - if (loadFieldPlugin == null || !loadFieldPlugin.apply((GraphBuilderContext) this, (ResolvedJavaField) field)) { - appendOptimizedLoadField(kind, genLoadField(null, (ResolvedJavaField) field)); - } - } else { - handleUnresolvedLoadField(field, null); - } - } - - public boolean tryLoadFieldPlugin(JavaField field, LoadFieldPlugin loadFieldPlugin) { - return loadFieldPlugin.apply((GraphBuilderContext) this, (ResolvedJavaField) field); - } - - private void genPutStatic(JavaField field) { - ValueNode value = frameState.pop(field.getKind().getStackKind()); - if (field instanceof ResolvedJavaField && ((ResolvedJavaType) field.getDeclaringClass()).isInitialized()) { - genStoreField(null, (ResolvedJavaField) field, value); - } else { - handleUnresolvedStoreField(field, value, null); - } - } - - protected void appendOptimizedLoadField(Kind kind, ValueNode load) { - // append the load to the instruction - ValueNode optimized = append(load); - frameState.push(kind.getStackKind(), optimized); - } - - protected abstract void genInvokeStatic(JavaMethod target); - - protected abstract void genInvokeInterface(JavaMethod target); - - protected abstract void genInvokeDynamic(JavaMethod target); - - protected abstract void genInvokeVirtual(JavaMethod target); - - protected abstract void genInvokeSpecial(JavaMethod target); - - protected abstract void genReturn(ValueNode x, Kind kind); - - protected abstract void genMonitorEnter(ValueNode x, int bci); - - protected abstract void genMonitorExit(ValueNode x, ValueNode returnValue, int bci); - - protected abstract void genJsr(int dest); - - protected abstract void genRet(int localIndex); - - private double[] switchProbability(int numberOfCases, int bci) { - double[] prob = (profilingInfo == null ? null : profilingInfo.getSwitchProbabilities(bci)); - if (prob != null) { - assert prob.length == numberOfCases; - } else { - Debug.log("Missing probability (switch) in %s at bci %d", method, bci); - prob = new double[numberOfCases]; - for (int i = 0; i < numberOfCases; i++) { - prob[i] = 1.0d / numberOfCases; - } - } - assert allPositive(prob); - return prob; - } - - private static boolean allPositive(double[] a) { - for (double d : a) { - if (d < 0) { - return false; - } - } - return true; - } - - /** - * Helper function that sums up the probabilities of all keys that lead to a specific successor. - * - * @return an array of size successorCount with the accumulated probability for each successor. - */ - public static double[] successorProbabilites(int successorCount, int[] keySuccessors, double[] keyProbabilities) { - double[] probability = new double[successorCount]; - for (int i = 0; i < keySuccessors.length; i++) { - probability[keySuccessors[i]] += keyProbabilities[i]; - } - return probability; - } - - private void genSwitch(BytecodeSwitch bs) { - int bci = bci(); - ValueNode value = frameState.ipop(); - - int nofCases = bs.numberOfCases(); - double[] keyProbabilities = switchProbability(nofCases + 1, bci); - - Map bciToBlockSuccessorIndex = new HashMap<>(); - for (int i = 0; i < currentBlock.getSuccessorCount(); i++) { - assert !bciToBlockSuccessorIndex.containsKey(currentBlock.getSuccessor(i).startBci); - if (!bciToBlockSuccessorIndex.containsKey(currentBlock.getSuccessor(i).startBci)) { - bciToBlockSuccessorIndex.put(currentBlock.getSuccessor(i).startBci, new SuccessorInfo(i)); - } - } - - ArrayList actualSuccessors = new ArrayList<>(); - int[] keys = new int[nofCases]; - int[] keySuccessors = new int[nofCases + 1]; - int deoptSuccessorIndex = -1; - int nextSuccessorIndex = 0; - boolean constantValue = value.isConstant(); - for (int i = 0; i < nofCases + 1; i++) { - if (i < nofCases) { - keys[i] = bs.keyAt(i); - } - - if (!constantValue && isNeverExecutedCode(keyProbabilities[i])) { - if (deoptSuccessorIndex < 0) { - deoptSuccessorIndex = nextSuccessorIndex++; - actualSuccessors.add(null); - } - keySuccessors[i] = deoptSuccessorIndex; - } else { - int targetBci = i >= nofCases ? bs.defaultTarget() : bs.targetAt(i); - SuccessorInfo info = bciToBlockSuccessorIndex.get(targetBci); - if (info.actualIndex < 0) { - info.actualIndex = nextSuccessorIndex++; - actualSuccessors.add(currentBlock.getSuccessor(info.blockIndex)); - } - keySuccessors[i] = info.actualIndex; - } - } - - genIntegerSwitch(value, actualSuccessors, keys, keyProbabilities, keySuccessors); - - } - - protected abstract void genIntegerSwitch(ValueNode value, ArrayList actualSuccessors, int[] keys, double[] keyProbabilities, int[] keySuccessors); - - private static class SuccessorInfo { - - int blockIndex; - int actualIndex; - - public SuccessorInfo(int blockSuccessorIndex) { - this.blockIndex = blockSuccessorIndex; - actualIndex = -1; - } - } - - protected abstract ValueNode appendConstant(JavaConstant constant); - - protected abstract T append(T v); - - protected boolean isNeverExecutedCode(double probability) { - return probability == 0 && optimisticOpts.removeNeverExecutedCode(); - } - - protected double branchProbability() { - if (profilingInfo == null) { - return 0.5; - } - assert assertAtIfBytecode(); - double probability = profilingInfo.getBranchTakenProbability(bci()); - if (probability < 0) { - assert probability == -1 : "invalid probability"; - Debug.log("missing probability in %s at bci %d", method, bci()); - probability = 0.5; - } - - if (!optimisticOpts.removeNeverExecutedCode()) { - if (probability == 0) { - probability = 0.0000001; - } else if (probability == 1) { - probability = 0.999999; - } - } - return probability; - } - - private boolean assertAtIfBytecode() { - int bytecode = stream.currentBC(); - switch (bytecode) { - case IFEQ: - case IFNE: - case IFLT: - case IFGE: - case IFGT: - case IFLE: - case IF_ICMPEQ: - case IF_ICMPNE: - case IF_ICMPLT: - case IF_ICMPGE: - case IF_ICMPGT: - case IF_ICMPLE: - case IF_ACMPEQ: - case IF_ACMPNE: - case IFNULL: - case IFNONNULL: - return true; - } - assert false : String.format("%x is not an if bytecode", bytecode); - return true; - } - - protected abstract void iterateBytecodesForBlock(BciBlock block); - - public final void processBytecode(int bci, int opcode) { - int cpi; - - // Checkstyle: stop - // @formatter:off - switch (opcode) { - case NOP : /* nothing to do */ break; - case ACONST_NULL : frameState.apush(appendConstant(JavaConstant.NULL_POINTER)); break; - case ICONST_M1 : // fall through - case ICONST_0 : // fall through - case ICONST_1 : // fall through - case ICONST_2 : // fall through - case ICONST_3 : // fall through - case ICONST_4 : // fall through - case ICONST_5 : frameState.ipush(appendConstant(JavaConstant.forInt(opcode - ICONST_0))); break; - case LCONST_0 : // fall through - case LCONST_1 : frameState.lpush(appendConstant(JavaConstant.forLong(opcode - LCONST_0))); break; - case FCONST_0 : // fall through - case FCONST_1 : // fall through - case FCONST_2 : frameState.fpush(appendConstant(JavaConstant.forFloat(opcode - FCONST_0))); break; - case DCONST_0 : // fall through - case DCONST_1 : frameState.dpush(appendConstant(JavaConstant.forDouble(opcode - DCONST_0))); break; - case BIPUSH : frameState.ipush(appendConstant(JavaConstant.forInt(stream.readByte()))); break; - case SIPUSH : frameState.ipush(appendConstant(JavaConstant.forInt(stream.readShort()))); break; - case LDC : // fall through - case LDC_W : // fall through - case LDC2_W : genLoadConstant(stream.readCPI(), opcode); break; - case ILOAD : loadLocal(stream.readLocalIndex(), Kind.Int); break; - case LLOAD : loadLocal(stream.readLocalIndex(), Kind.Long); break; - case FLOAD : loadLocal(stream.readLocalIndex(), Kind.Float); break; - case DLOAD : loadLocal(stream.readLocalIndex(), Kind.Double); break; - case ALOAD : loadLocal(stream.readLocalIndex(), Kind.Object); break; - case ILOAD_0 : // fall through - case ILOAD_1 : // fall through - case ILOAD_2 : // fall through - case ILOAD_3 : loadLocal(opcode - ILOAD_0, Kind.Int); break; - case LLOAD_0 : // fall through - case LLOAD_1 : // fall through - case LLOAD_2 : // fall through - case LLOAD_3 : loadLocal(opcode - LLOAD_0, Kind.Long); break; - case FLOAD_0 : // fall through - case FLOAD_1 : // fall through - case FLOAD_2 : // fall through - case FLOAD_3 : loadLocal(opcode - FLOAD_0, Kind.Float); break; - case DLOAD_0 : // fall through - case DLOAD_1 : // fall through - case DLOAD_2 : // fall through - case DLOAD_3 : loadLocal(opcode - DLOAD_0, Kind.Double); break; - case ALOAD_0 : // fall through - case ALOAD_1 : // fall through - case ALOAD_2 : // fall through - case ALOAD_3 : loadLocal(opcode - ALOAD_0, Kind.Object); break; - case IALOAD : genLoadIndexed(Kind.Int ); break; - case LALOAD : genLoadIndexed(Kind.Long ); break; - case FALOAD : genLoadIndexed(Kind.Float ); break; - case DALOAD : genLoadIndexed(Kind.Double); break; - case AALOAD : genLoadIndexed(Kind.Object); break; - case BALOAD : genLoadIndexed(Kind.Byte ); break; - case CALOAD : genLoadIndexed(Kind.Char ); break; - case SALOAD : genLoadIndexed(Kind.Short ); break; - case ISTORE : storeLocal(Kind.Int, stream.readLocalIndex()); break; - case LSTORE : storeLocal(Kind.Long, stream.readLocalIndex()); break; - case FSTORE : storeLocal(Kind.Float, stream.readLocalIndex()); break; - case DSTORE : storeLocal(Kind.Double, stream.readLocalIndex()); break; - case ASTORE : storeLocal(Kind.Object, stream.readLocalIndex()); break; - case ISTORE_0 : // fall through - case ISTORE_1 : // fall through - case ISTORE_2 : // fall through - case ISTORE_3 : storeLocal(Kind.Int, opcode - ISTORE_0); break; - case LSTORE_0 : // fall through - case LSTORE_1 : // fall through - case LSTORE_2 : // fall through - case LSTORE_3 : storeLocal(Kind.Long, opcode - LSTORE_0); break; - case FSTORE_0 : // fall through - case FSTORE_1 : // fall through - case FSTORE_2 : // fall through - case FSTORE_3 : storeLocal(Kind.Float, opcode - FSTORE_0); break; - case DSTORE_0 : // fall through - case DSTORE_1 : // fall through - case DSTORE_2 : // fall through - case DSTORE_3 : storeLocal(Kind.Double, opcode - DSTORE_0); break; - case ASTORE_0 : // fall through - case ASTORE_1 : // fall through - case ASTORE_2 : // fall through - case ASTORE_3 : storeLocal(Kind.Object, opcode - ASTORE_0); break; - case IASTORE : genStoreIndexed(Kind.Int ); break; - case LASTORE : genStoreIndexed(Kind.Long ); break; - case FASTORE : genStoreIndexed(Kind.Float ); break; - case DASTORE : genStoreIndexed(Kind.Double); break; - case AASTORE : genStoreIndexed(Kind.Object); break; - case BASTORE : genStoreIndexed(Kind.Byte ); break; - case CASTORE : genStoreIndexed(Kind.Char ); break; - case SASTORE : genStoreIndexed(Kind.Short ); break; - case POP : frameState.xpop(); break; - case POP2 : frameState.xpop(); frameState.xpop(); break; - case DUP : frameState.xpush(frameState.xpeek()); break; - case DUP_X1 : // fall through - case DUP_X2 : // fall through - case DUP2 : // fall through - case DUP2_X1 : // fall through - case DUP2_X2 : // fall through - case SWAP : stackOp(opcode); break; - case IADD : // fall through - case ISUB : // fall through - case IMUL : genArithmeticOp(Kind.Int, opcode); break; - case IDIV : // fall through - case IREM : genIntegerDivOp(Kind.Int, opcode); break; - case LADD : // fall through - case LSUB : // fall through - case LMUL : genArithmeticOp(Kind.Long, opcode); break; - case LDIV : // fall through - case LREM : genIntegerDivOp(Kind.Long, opcode); break; - case FADD : // fall through - case FSUB : // fall through - case FMUL : // fall through - case FDIV : // fall through - case FREM : genArithmeticOp(Kind.Float, opcode); break; - case DADD : // fall through - case DSUB : // fall through - case DMUL : // fall through - case DDIV : // fall through - case DREM : genArithmeticOp(Kind.Double, opcode); break; - case INEG : genNegateOp(Kind.Int); break; - case LNEG : genNegateOp(Kind.Long); break; - case FNEG : genNegateOp(Kind.Float); break; - case DNEG : genNegateOp(Kind.Double); break; - case ISHL : // fall through - case ISHR : // fall through - case IUSHR : genShiftOp(Kind.Int, opcode); break; - case IAND : // fall through - case IOR : // fall through - case IXOR : genLogicOp(Kind.Int, opcode); break; - case LSHL : // fall through - case LSHR : // fall through - case LUSHR : genShiftOp(Kind.Long, opcode); break; - case LAND : // fall through - case LOR : // fall through - case LXOR : genLogicOp(Kind.Long, opcode); break; - case IINC : genIncrement(); break; - case I2F : genFloatConvert(FloatConvert.I2F, Kind.Int, Kind.Float); break; - case I2D : genFloatConvert(FloatConvert.I2D, Kind.Int, Kind.Double); break; - case L2F : genFloatConvert(FloatConvert.L2F, Kind.Long, Kind.Float); break; - case L2D : genFloatConvert(FloatConvert.L2D, Kind.Long, Kind.Double); break; - case F2I : genFloatConvert(FloatConvert.F2I, Kind.Float, Kind.Int); break; - case F2L : genFloatConvert(FloatConvert.F2L, Kind.Float, Kind.Long); break; - case F2D : genFloatConvert(FloatConvert.F2D, Kind.Float, Kind.Double); break; - case D2I : genFloatConvert(FloatConvert.D2I, Kind.Double, Kind.Int); break; - case D2L : genFloatConvert(FloatConvert.D2L, Kind.Double, Kind.Long); break; - case D2F : genFloatConvert(FloatConvert.D2F, Kind.Double, Kind.Float); break; - case L2I : genNarrow(Kind.Long, Kind.Int); break; - case I2L : genSignExtend(Kind.Int, Kind.Long); break; - case I2B : genSignExtend(Kind.Byte, Kind.Int); break; - case I2S : genSignExtend(Kind.Short, Kind.Int); break; - case I2C : genZeroExtend(Kind.Char, Kind.Int); break; - case LCMP : genCompareOp(Kind.Long, false); break; - case FCMPL : genCompareOp(Kind.Float, true); break; - case FCMPG : genCompareOp(Kind.Float, false); break; - case DCMPL : genCompareOp(Kind.Double, true); break; - case DCMPG : genCompareOp(Kind.Double, false); break; - case IFEQ : genIfZero(Condition.EQ); break; - case IFNE : genIfZero(Condition.NE); break; - case IFLT : genIfZero(Condition.LT); break; - case IFGE : genIfZero(Condition.GE); break; - case IFGT : genIfZero(Condition.GT); break; - case IFLE : genIfZero(Condition.LE); break; - case IF_ICMPEQ : genIfSame(Kind.Int, Condition.EQ); break; - case IF_ICMPNE : genIfSame(Kind.Int, Condition.NE); break; - case IF_ICMPLT : genIfSame(Kind.Int, Condition.LT); break; - case IF_ICMPGE : genIfSame(Kind.Int, Condition.GE); break; - case IF_ICMPGT : genIfSame(Kind.Int, Condition.GT); break; - case IF_ICMPLE : genIfSame(Kind.Int, Condition.LE); break; - case IF_ACMPEQ : genIfSame(Kind.Object, Condition.EQ); break; - case IF_ACMPNE : genIfSame(Kind.Object, Condition.NE); break; - case GOTO : genGoto(); break; - case JSR : genJsr(stream.readBranchDest()); break; - case RET : genRet(stream.readLocalIndex()); break; - case TABLESWITCH : genSwitch(new BytecodeTableSwitch(getStream(), bci())); break; - case LOOKUPSWITCH : genSwitch(new BytecodeLookupSwitch(getStream(), bci())); break; - case IRETURN : genReturn(frameState.ipop(), Kind.Int); break; - case LRETURN : genReturn(frameState.lpop(), Kind.Long); break; - case FRETURN : genReturn(frameState.fpop(), Kind.Float); break; - case DRETURN : genReturn(frameState.dpop(), Kind.Double); break; - case ARETURN : genReturn(frameState.apop(), Kind.Object); break; - case RETURN : genReturn(null, Kind.Void); break; - case GETSTATIC : cpi = stream.readCPI(); genGetStatic(lookupField(cpi, opcode)); break; - case PUTSTATIC : cpi = stream.readCPI(); genPutStatic(lookupField(cpi, opcode)); break; - case GETFIELD : cpi = stream.readCPI(); genGetField(lookupField(cpi, opcode)); break; - case PUTFIELD : cpi = stream.readCPI(); genPutField(lookupField(cpi, opcode)); break; - case INVOKEVIRTUAL : cpi = stream.readCPI(); genInvokeVirtual(lookupMethod(cpi, opcode)); break; - case INVOKESPECIAL : cpi = stream.readCPI(); genInvokeSpecial(lookupMethod(cpi, opcode)); break; - case INVOKESTATIC : cpi = stream.readCPI(); genInvokeStatic(lookupMethod(cpi, opcode)); break; - case INVOKEINTERFACE: cpi = stream.readCPI(); genInvokeInterface(lookupMethod(cpi, opcode)); break; - case INVOKEDYNAMIC : cpi = stream.readCPI4(); genInvokeDynamic(lookupMethod(cpi, opcode)); break; - case NEW : genNewInstance(stream.readCPI()); break; - case NEWARRAY : genNewPrimitiveArray(stream.readLocalIndex()); break; - case ANEWARRAY : genNewObjectArray(stream.readCPI()); break; - case ARRAYLENGTH : genArrayLength(); break; - case ATHROW : genThrow(); break; - case CHECKCAST : genCheckCast(); break; - case INSTANCEOF : genInstanceOf(); break; - case MONITORENTER : genMonitorEnter(frameState.apop(), stream.nextBCI()); break; - case MONITOREXIT : genMonitorExit(frameState.apop(), null, stream.nextBCI()); break; - case MULTIANEWARRAY : genNewMultiArray(stream.readCPI()); break; - case IFNULL : genIfNull(Condition.EQ); break; - case IFNONNULL : genIfNull(Condition.NE); break; - case GOTO_W : genGoto(); break; - case JSR_W : genJsr(stream.readBranchDest()); break; - case BREAKPOINT: - throw new BailoutException("concurrent setting of breakpoint"); - default: - throw new BailoutException("Unsupported opcode %d (%s) [bci=%d]", opcode, nameOf(opcode), bci); - } - // @formatter:on - // Checkstyle: resume - } - - private void genArrayLength() { - frameState.ipush(append(genArrayLength(frameState.apop()))); - } - - public ResolvedJavaMethod getMethod() { - return method; - } - - public HIRFrameStateBuilder getFrameState() { - return frameState; - } - - protected boolean traceInstruction(int bci, int opcode, boolean blockStart) { - if (Debug.isEnabled() && Options.TraceBytecodeParserLevel.getValue() >= TRACELEVEL_INSTRUCTIONS && Debug.isLogEnabled()) { - traceInstructionHelper(bci, opcode, blockStart); - } - return true; - } - - private void traceInstructionHelper(int bci, int opcode, boolean blockStart) { - StringBuilder sb = new StringBuilder(40); - sb.append(blockStart ? '+' : '|'); - if (bci < 10) { - sb.append(" "); - } else if (bci < 100) { - sb.append(' '); - } - sb.append(bci).append(": ").append(Bytecodes.nameOf(opcode)); - for (int i = bci + 1; i < stream.nextBCI(); ++i) { - sb.append(' ').append(stream.readUByte(i)); - } - if (!currentBlock.getJsrScope().isEmpty()) { - sb.append(' ').append(currentBlock.getJsrScope()); - } - Debug.log("%s", sb); - } - - public boolean parsingIntrinsic() { - return intrinsicContext != null; - } -} diff -r e34bc00733d1 -r acfc5e32e678 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Tue May 12 17:29:49 2015 -0700 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Tue May 12 18:04:53 2015 -0700 @@ -22,6 +22,7 @@ */ package com.oracle.graal.java; +import static com.oracle.graal.api.code.TypeCheckHints.*; import static com.oracle.graal.api.meta.DeoptimizationAction.*; import static com.oracle.graal.api.meta.DeoptimizationReason.*; import static com.oracle.graal.bytecode.Bytecodes.*; @@ -29,7 +30,7 @@ import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.compiler.common.type.StampFactory.*; import static com.oracle.graal.graphbuilderconf.IntrinsicContext.CompilationContext.*; -import static com.oracle.graal.java.AbstractBytecodeParser.Options.*; +import static com.oracle.graal.java.GraphBuilderPhase.Options.*; import static com.oracle.graal.nodes.StructuredGraph.*; import static com.oracle.graal.nodes.type.StampTool.*; import static java.lang.String.*; @@ -63,6 +64,7 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; +import com.oracle.graal.options.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.tiers.*; @@ -71,6 +73,125 @@ */ public class GraphBuilderPhase extends BasePhase { + public static class Options { + // @formatter:off + @Option(help = "The trace level for the bytecode parser used when building a graph from bytecode", type = OptionType.Debug) + public static final OptionValue TraceBytecodeParserLevel = new OptionValue<>(0); + + @Option(help = "Inlines trivial methods during bytecode parsing.", type = OptionType.Expert) + public static final StableOptionValue InlineDuringParsing = new StableOptionValue<>(false); + + @Option(help = "Inlines intrinsic methods during bytecode parsing.", type = OptionType.Expert) + public static final StableOptionValue InlineIntrinsicsDuringParsing = new StableOptionValue<>(true); + + @Option(help = "Traces inlining performed during bytecode parsing.", type = OptionType.Debug) + public static final StableOptionValue TraceInlineDuringParsing = new StableOptionValue<>(false); + + @Option(help = "Traces use of plugins during bytecode parsing.", type = OptionType.Debug) + public static final StableOptionValue TraceParserPlugins = new StableOptionValue<>(false); + + @Option(help = "Maximum depth when inlining during bytecode parsing.", type = OptionType.Debug) + public static final StableOptionValue InlineDuringParsingMaxDepth = new StableOptionValue<>(10); + + @Option(help = "Dump graphs after non-trivial changes during bytecode parsing.", type = OptionType.Debug) + public static final StableOptionValue DumpDuringGraphBuilding = new StableOptionValue<>(false); + + @Option(help = "Max number of loop explosions per method.", type = OptionType.Debug) + public static final OptionValue MaximumLoopExplosionCount = new OptionValue<>(10000); + + @Option(help = "Do not bail out but throw an exception on failed loop explosion.", type = OptionType.Debug) + public static final OptionValue FailedLoopExplosionIsFatal = new OptionValue<>(false); + + @Option(help = "When creating info points hide the methods of the substitutions.", type = OptionType.Debug) + public static final OptionValue HideSubstitutionStates = new OptionValue<>(false); + + // @formatter:on + } + + /** + * The minimum value to which {@link Options#TraceBytecodeParserLevel} must be set to trace the + * bytecode instructions as they are parsed. + */ + public static final int TRACELEVEL_INSTRUCTIONS = 1; + + /** + * The minimum value to which {@link Options#TraceBytecodeParserLevel} must be set to trace the + * frame state before each bytecode instruction as it is parsed. + */ + public static final int TRACELEVEL_STATE = 2; + + /** + * Meters the number of actual bytecodes parsed. + */ + public static final DebugMetric BytecodesParsed = Debug.metric("BytecodesParsed"); + + /** + * Gets the kind of array elements for the array type code that appears in a + * {@link Bytecodes#NEWARRAY} bytecode. + * + * @param code the array type code + * @return the kind from the array type code + */ + public static Class arrayTypeCodeToClass(int code) { + // Checkstyle: stop + switch (code) { + case 4: + return boolean.class; + case 5: + return char.class; + case 6: + return float.class; + case 7: + return double.class; + case 8: + return byte.class; + case 9: + return short.class; + case 10: + return int.class; + case 11: + return long.class; + default: + throw new IllegalArgumentException("unknown array type code: " + code); + } + // Checkstyle: resume + } + + protected static final DebugMetric EXPLICIT_EXCEPTIONS = Debug.metric("ExplicitExceptions"); + + protected static boolean allPositive(double[] a) { + for (double d : a) { + if (d < 0) { + return false; + } + } + return true; + } + + /** + * Helper function that sums up the probabilities of all keys that lead to a specific successor. + * + * @return an array of size successorCount with the accumulated probability for each successor. + */ + public static double[] successorProbabilites(int successorCount, int[] keySuccessors, double[] keyProbabilities) { + double[] probability = new double[successorCount]; + for (int i = 0; i < keySuccessors.length; i++) { + probability[keySuccessors[i]] += keyProbabilities[i]; + } + return probability; + } + + static class SuccessorInfo { + + int blockIndex; + int actualIndex; + + public SuccessorInfo(int blockSuccessorIndex) { + this.blockIndex = blockSuccessorIndex; + actualIndex = -1; + } + } + private final GraphBuilderConfiguration graphBuilderConfig; public GraphBuilderPhase(GraphBuilderConfiguration config) { @@ -305,7 +426,7 @@ } } - public class BytecodeParser extends AbstractBytecodeParser implements GraphBuilderContext { + public class BytecodeParser implements GraphBuilderContext { private BciBlockMapping blockMap; private LocalLiveness liveness; @@ -339,7 +460,15 @@ public BytecodeParser(BytecodeParser parent, MetaAccessProvider metaAccess, ResolvedJavaMethod method, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, int entryBCI, IntrinsicContext intrinsicContext) { - super(metaAccess, method, graphBuilderConfig, optimisticOpts, intrinsicContext); + this.graphBuilderConfig = graphBuilderConfig; + this.optimisticOpts = optimisticOpts; + this.metaAccess = metaAccess; + this.stream = new BytecodeStream(method.getCode()); + this.profilingInfo = (graphBuilderConfig.getUseProfiling() ? method.getProfilingInfo() : null); + this.constantPool = method.getConstantPool(); + this.method = method; + this.intrinsicContext = intrinsicContext; + assert metaAccess != null; this.entryBCI = entryBCI; this.parent = parent; @@ -743,7 +872,6 @@ /** * @param type the unresolved type of the constant */ - @Override protected void handleUnresolvedLoadConstant(JavaType type) { assert !graphBuilderConfig.eagerResolving(); append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); @@ -753,7 +881,6 @@ * @param type the unresolved type of the type check * @param object the object value whose type is being checked against {@code type} */ - @Override protected void handleUnresolvedCheckCast(JavaType type, ValueNode object) { assert !graphBuilderConfig.eagerResolving(); append(new FixedGuardNode(graph.unique(new IsNullNode(object)), Unresolved, InvalidateRecompile)); @@ -764,7 +891,6 @@ * @param type the unresolved type of the type check * @param object the object value whose type is being checked against {@code type} */ - @Override protected void handleUnresolvedInstanceOf(JavaType type, ValueNode object) { assert !graphBuilderConfig.eagerResolving(); AbstractBeginNode successor = graph.add(new BeginNode()); @@ -777,7 +903,6 @@ /** * @param type the type being instantiated */ - @Override protected void handleUnresolvedNewInstance(JavaType type) { assert !graphBuilderConfig.eagerResolving(); append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); @@ -787,7 +912,6 @@ * @param type the type of the array being instantiated * @param length the length of the array */ - @Override protected void handleUnresolvedNewObjectArray(JavaType type, ValueNode length) { assert !graphBuilderConfig.eagerResolving(); append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); @@ -797,7 +921,6 @@ * @param type the type being instantiated * @param dims the dimensions for the multi-array */ - @Override protected void handleUnresolvedNewMultiArray(JavaType type, List dims) { assert !graphBuilderConfig.eagerResolving(); append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); @@ -808,7 +931,6 @@ * @param receiver the object containing the field or {@code null} if {@code field} is * static */ - @Override protected void handleUnresolvedLoadField(JavaField field, ValueNode receiver) { assert !graphBuilderConfig.eagerResolving(); append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); @@ -820,7 +942,6 @@ * @param receiver the object containing the field or {@code null} if {@code field} is * static */ - @Override protected void handleUnresolvedStoreField(JavaField field, ValueNode value, ValueNode receiver) { assert !graphBuilderConfig.eagerResolving(); append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); @@ -829,7 +950,6 @@ /** * @param type */ - @Override protected void handleUnresolvedExceptionType(JavaType type) { assert !graphBuilderConfig.eagerResolving(); append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); @@ -880,148 +1000,119 @@ return dispatchBegin; } - @Override protected ValueNode genLoadIndexed(ValueNode array, ValueNode index, Kind kind) { return LoadIndexedNode.create(array, index, kind, metaAccess, constantReflection); } - @Override protected void genStoreIndexed(ValueNode array, ValueNode index, Kind kind, ValueNode value) { add(new StoreIndexedNode(array, index, kind, value)); } - @Override - protected ValueNode genIntegerAdd(Kind kind, ValueNode x, ValueNode y) { + protected ValueNode genIntegerAdd(ValueNode x, ValueNode y) { return AddNode.create(x, y); } - @Override - protected ValueNode genIntegerSub(Kind kind, ValueNode x, ValueNode y) { + protected ValueNode genIntegerSub(ValueNode x, ValueNode y) { return SubNode.create(x, y); } - @Override - protected ValueNode genIntegerMul(Kind kind, ValueNode x, ValueNode y) { + protected ValueNode genIntegerMul(ValueNode x, ValueNode y) { return MulNode.create(x, y); } - @Override - protected ValueNode genFloatAdd(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) { + protected ValueNode genFloatAdd(ValueNode x, ValueNode y) { return AddNode.create(x, y); } - @Override - protected ValueNode genFloatSub(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) { + protected ValueNode genFloatSub(ValueNode x, ValueNode y) { return SubNode.create(x, y); } - @Override - protected ValueNode genFloatMul(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) { + protected ValueNode genFloatMul(ValueNode x, ValueNode y) { return MulNode.create(x, y); } - @Override - protected ValueNode genFloatDiv(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) { + protected ValueNode genFloatDiv(ValueNode x, ValueNode y) { return DivNode.create(x, y); } - @Override - protected ValueNode genFloatRem(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) { + protected ValueNode genFloatRem(ValueNode x, ValueNode y) { return new RemNode(x, y); } - @Override - protected ValueNode genIntegerDiv(Kind kind, ValueNode x, ValueNode y) { + protected ValueNode genIntegerDiv(ValueNode x, ValueNode y) { return new IntegerDivNode(x, y); } - @Override - protected ValueNode genIntegerRem(Kind kind, ValueNode x, ValueNode y) { + protected ValueNode genIntegerRem(ValueNode x, ValueNode y) { return new IntegerRemNode(x, y); } - @Override protected ValueNode genNegateOp(ValueNode x) { return (new NegateNode(x)); } - @Override - protected ValueNode genLeftShift(Kind kind, ValueNode x, ValueNode y) { + protected ValueNode genLeftShift(ValueNode x, ValueNode y) { return new LeftShiftNode(x, y); } - @Override - protected ValueNode genRightShift(Kind kind, ValueNode x, ValueNode y) { + protected ValueNode genRightShift(ValueNode x, ValueNode y) { return new RightShiftNode(x, y); } - @Override - protected ValueNode genUnsignedRightShift(Kind kind, ValueNode x, ValueNode y) { + protected ValueNode genUnsignedRightShift(ValueNode x, ValueNode y) { return new UnsignedRightShiftNode(x, y); } - @Override - protected ValueNode genAnd(Kind kind, ValueNode x, ValueNode y) { + protected ValueNode genAnd(ValueNode x, ValueNode y) { return AndNode.create(x, y); } - @Override - protected ValueNode genOr(Kind kind, ValueNode x, ValueNode y) { + protected ValueNode genOr(ValueNode x, ValueNode y) { return OrNode.create(x, y); } - @Override - protected ValueNode genXor(Kind kind, ValueNode x, ValueNode y) { + protected ValueNode genXor(ValueNode x, ValueNode y) { return XorNode.create(x, y); } - @Override protected ValueNode genNormalizeCompare(ValueNode x, ValueNode y, boolean isUnorderedLess) { return NormalizeCompareNode.create(x, y, isUnorderedLess, constantReflection); } - @Override protected ValueNode genFloatConvert(FloatConvert op, ValueNode input) { return FloatConvertNode.create(op, input); } - @Override protected ValueNode genNarrow(ValueNode input, int bitCount) { return NarrowNode.create(input, bitCount); } - @Override protected ValueNode genSignExtend(ValueNode input, int bitCount) { return SignExtendNode.create(input, bitCount); } - @Override protected ValueNode genZeroExtend(ValueNode input, int bitCount) { return ZeroExtendNode.create(input, bitCount); } - @Override protected void genGoto() { appendGoto(currentBlock.getSuccessor(0)); assert currentBlock.numNormalSuccessors() == 1; } - @Override protected LogicNode genObjectEquals(ValueNode x, ValueNode y) { return ObjectEqualsNode.create(x, y, constantReflection); } - @Override protected LogicNode genIntegerEquals(ValueNode x, ValueNode y) { return IntegerEqualsNode.create(x, y, constantReflection); } - @Override protected LogicNode genIntegerLessThan(ValueNode x, ValueNode y) { return IntegerLessThanNode.create(x, y, constantReflection); } - @Override protected ValueNode genUnique(ValueNode x) { return (ValueNode) graph.unique((Node & ValueNumberable) x); } @@ -1030,49 +1121,40 @@ return new IfNode(condition, falseSuccessor, trueSuccessor, d); } - @Override protected void genThrow() { ValueNode exception = frameState.apop(); append(new FixedGuardNode(graph.unique(new IsNullNode(exception)), NullCheckException, InvalidateReprofile, true)); lastInstr.setNext(handleException(exception, bci())); } - @Override protected ValueNode createCheckCast(ResolvedJavaType type, ValueNode object, JavaTypeProfile profileForTypeCheck, boolean forStoreCheck) { return CheckCastNode.create(type, object, profileForTypeCheck, forStoreCheck, graph.getAssumptions()); } - @Override protected ValueNode createInstanceOf(ResolvedJavaType type, ValueNode object, JavaTypeProfile profileForTypeCheck) { return InstanceOfNode.create(type, object, profileForTypeCheck); } - @Override protected ValueNode genConditional(ValueNode x) { return new ConditionalNode((LogicNode) x); } - @Override protected NewInstanceNode createNewInstance(ResolvedJavaType type, boolean fillContents) { return new NewInstanceNode(type, fillContents); } - @Override protected NewArrayNode createNewArray(ResolvedJavaType elementType, ValueNode length, boolean fillContents) { return new NewArrayNode(elementType, length, fillContents); } - @Override protected NewMultiArrayNode createNewMultiArray(ResolvedJavaType type, List dimensions) { return new NewMultiArrayNode(type, dimensions.toArray(new ValueNode[0])); } - @Override protected ValueNode genLoadField(ValueNode receiver, ResolvedJavaField field) { return new LoadFieldNode(receiver, field); } - @Override protected ValueNode emitExplicitNullCheck(ValueNode receiver) { if (StampTool.isPointerNonNull(receiver.stamp())) { return receiver; @@ -1089,7 +1171,6 @@ return nonNullReceiver; } - @Override protected void emitExplicitBoundsCheck(ValueNode index, ValueNode length) { AbstractBeginNode trueSucc = graph.add(new BeginNode()); BytecodeExceptionNode exception = graph.add(new BytecodeExceptionNode(metaAccess, ArrayIndexOutOfBoundsException.class, index)); @@ -1100,12 +1181,10 @@ exception.setNext(handleException(exception, bci())); } - @Override protected ValueNode genArrayLength(ValueNode x) { return ArrayLengthNode.create(x, constantReflection); } - @Override protected void genStoreField(ValueNode receiver, ResolvedJavaField field, ValueNode value) { StoreFieldNode storeFieldNode = new StoreFieldNode(receiver, field, value); append(storeFieldNode); @@ -1128,7 +1207,6 @@ return false; } - @Override protected void genInvokeStatic(JavaMethod target) { if (callTargetIsResolved(target)) { ResolvedJavaMethod resolvedTarget = (ResolvedJavaMethod) target; @@ -1144,7 +1222,6 @@ } } - @Override protected void genInvokeInterface(JavaMethod target) { if (callTargetIsResolved(target)) { ValueNode[] args = frameState.popArguments(target.getSignature().getParameterCount(true)); @@ -1154,7 +1231,6 @@ } } - @Override protected void genInvokeDynamic(JavaMethod target) { if (target instanceof ResolvedJavaMethod) { JavaConstant appendix = constantPool.lookupAppendix(stream.readCPI4(), Bytecodes.INVOKEDYNAMIC); @@ -1168,7 +1244,6 @@ } } - @Override protected void genInvokeVirtual(JavaMethod target) { if (callTargetIsResolved(target)) { /* @@ -1195,7 +1270,6 @@ } - @Override protected void genInvokeSpecial(JavaMethod target) { if (callTargetIsResolved(target)) { assert target != null; @@ -1209,6 +1283,16 @@ private InvokeKind currentInvokeKind; private JavaType currentInvokeReturnType; + protected HIRFrameStateBuilder frameState; + protected BciBlock currentBlock; + protected final BytecodeStream stream; + protected final GraphBuilderConfiguration graphBuilderConfig; + protected final ResolvedJavaMethod method; + protected final ProfilingInfo profilingInfo; + protected final OptimisticOptimizations optimisticOpts; + protected final ConstantPool constantPool; + protected final MetaAccessProvider metaAccess; + protected final IntrinsicContext intrinsicContext; public InvokeKind getInvokeKind() { return currentInvokeKind; @@ -1466,7 +1550,7 @@ * @param format a format string * @param args arguments to the format string */ - @Override + protected void traceWithContext(String format, Object... args) { StackTraceElement where = method.asStackTraceElement(bci()); TTY.println(format("%s%s (%s:%d) %s", nSpaces(getDepth()), method.isConstructor() ? method.format("%h.%n") : method.getName(), where.getFileName(), where.getLineNumber(), @@ -1540,7 +1624,6 @@ return invoke; } - @Override protected void genReturn(ValueNode returnVal, Kind returnKind) { if (parsingIntrinsic() && returnVal != null) { if (returnVal instanceof StateSplit) { @@ -1603,7 +1686,6 @@ } } - @Override protected void genMonitorEnter(ValueNode x, int bci) { MonitorIdNode monitorId = graph.add(new MonitorIdNode(frameState.lockDepth())); MonitorEnterNode monitorEnter = append(new MonitorEnterNode(x, monitorId)); @@ -1611,7 +1693,6 @@ monitorEnter.setStateAfter(createFrameState(bci, monitorEnter)); } - @Override protected void genMonitorExit(ValueNode x, ValueNode escapedReturnValue, int bci) { MonitorIdNode monitorId = frameState.peekMonitorId(); ValueNode lockedObject = frameState.popLock(); @@ -1622,7 +1703,6 @@ monitorExit.setStateAfter(createFrameState(bci, monitorExit)); } - @Override protected void genJsr(int dest) { BciBlock successor = currentBlock.getJsrSuccessor(); assert successor.startBci == dest : successor.startBci + " != " + dest + " @" + bci(); @@ -1639,7 +1719,6 @@ appendGoto(successor); } - @Override protected void genRet(int localIndex) { BciBlock successor = currentBlock.getRetSuccessor(); ValueNode local = frameState.loadLocal(localIndex); @@ -1662,7 +1741,6 @@ return graph.unique(nextBciNode); } - @Override protected void genIntegerSwitch(ValueNode value, ArrayList actualSuccessors, int[] keys, double[] keyProbabilities, int[] keySuccessors) { if (value.isConstant()) { JavaConstant constant = (JavaConstant) value.asConstant(); @@ -1684,7 +1762,6 @@ } } - @Override protected ConstantNode appendConstant(JavaConstant constant) { assert constant != null; return ConstantNode.forConstant(constant, metaAccess, graph); @@ -2187,7 +2264,6 @@ } } - @Override protected void iterateBytecodesForBlock(BciBlock block) { if (block.isLoopHeader && !explodeLoops) { // Create the loop header block, which later will merge the backward branches of @@ -2350,7 +2426,6 @@ } } - @Override protected void genIf(ValueNode x, Condition cond, ValueNode y) { assert currentBlock.getSuccessorCount() == 2; BciBlock trueBlock = currentBlock.getSuccessor(0); @@ -2600,6 +2675,894 @@ private BytecodePosition createBytecodePosition() { return frameState.createBytecodePosition(bci()); } + + public void setCurrentFrameState(HIRFrameStateBuilder frameState) { + this.frameState = frameState; + } + + protected final BytecodeStream getStream() { + return stream; + } + + public int bci() { + return stream.currentBCI(); + } + + public void loadLocal(int index, Kind kind) { + frameState.push(kind, frameState.loadLocal(index)); + } + + public void storeLocal(Kind kind, int index) { + ValueNode value; + if (kind == Kind.Object) { + value = frameState.xpop(); + // astore and astore_ may be used to store a returnAddress (jsr) + assert parsingIntrinsic() || (value.getKind() == Kind.Object || value.getKind() == Kind.Int) : value + ":" + value.getKind(); + } else { + value = frameState.pop(kind); + } + frameState.storeLocal(index, value, kind); + } + + private void genLoadConstant(int cpi, int opcode) { + Object con = lookupConstant(cpi, opcode); + + if (con instanceof JavaType) { + // this is a load of class constant which might be unresolved + JavaType type = (JavaType) con; + if (type instanceof ResolvedJavaType) { + frameState.push(Kind.Object, appendConstant(((ResolvedJavaType) type).getJavaClass())); + } else { + handleUnresolvedLoadConstant(type); + } + } else if (con instanceof JavaConstant) { + JavaConstant constant = (JavaConstant) con; + frameState.push(constant.getKind().getStackKind(), appendConstant(constant)); + } else { + throw new Error("lookupConstant returned an object of incorrect type"); + } + } + + private void genLoadIndexed(Kind kind) { + ValueNode index = frameState.ipop(); + ValueNode array = emitExplicitExceptions(frameState.apop(), index); + if (!tryLoadIndexedPlugin(kind, index, array)) { + frameState.push(kind.getStackKind(), append(genLoadIndexed(array, index, kind))); + } + } + + protected boolean tryLoadIndexedPlugin(Kind kind, ValueNode index, ValueNode array) { + LoadIndexedPlugin loadIndexedPlugin = graphBuilderConfig.getPlugins().getLoadIndexedPlugin(); + if (loadIndexedPlugin != null && loadIndexedPlugin.apply(this, array, index, kind)) { + if (TraceParserPlugins.getValue()) { + traceWithContext("used load indexed plugin"); + } + return true; + } else { + return false; + } + } + + private void genStoreIndexed(Kind kind) { + ValueNode value = frameState.pop(kind.getStackKind()); + ValueNode index = frameState.ipop(); + ValueNode array = emitExplicitExceptions(frameState.apop(), index); + genStoreIndexed(array, index, kind, value); + } + + private void stackOp(int opcode) { + switch (opcode) { + case DUP_X1: { + ValueNode w1 = frameState.xpop(); + ValueNode w2 = frameState.xpop(); + frameState.xpush(w1); + frameState.xpush(w2); + frameState.xpush(w1); + break; + } + case DUP_X2: { + ValueNode w1 = frameState.xpop(); + ValueNode w2 = frameState.xpop(); + ValueNode w3 = frameState.xpop(); + frameState.xpush(w1); + frameState.xpush(w3); + frameState.xpush(w2); + frameState.xpush(w1); + break; + } + case DUP2: { + ValueNode w1 = frameState.xpop(); + ValueNode w2 = frameState.xpop(); + frameState.xpush(w2); + frameState.xpush(w1); + frameState.xpush(w2); + frameState.xpush(w1); + break; + } + case DUP2_X1: { + ValueNode w1 = frameState.xpop(); + ValueNode w2 = frameState.xpop(); + ValueNode w3 = frameState.xpop(); + frameState.xpush(w2); + frameState.xpush(w1); + frameState.xpush(w3); + frameState.xpush(w2); + frameState.xpush(w1); + break; + } + case DUP2_X2: { + ValueNode w1 = frameState.xpop(); + ValueNode w2 = frameState.xpop(); + ValueNode w3 = frameState.xpop(); + ValueNode w4 = frameState.xpop(); + frameState.xpush(w2); + frameState.xpush(w1); + frameState.xpush(w4); + frameState.xpush(w3); + frameState.xpush(w2); + frameState.xpush(w1); + break; + } + case SWAP: { + ValueNode w1 = frameState.xpop(); + ValueNode w2 = frameState.xpop(); + frameState.xpush(w1); + frameState.xpush(w2); + break; + } + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + private void genArithmeticOp(Kind result, int opcode) { + ValueNode y = frameState.pop(result); + ValueNode x = frameState.pop(result); + ValueNode v; + switch (opcode) { + case IADD: + case LADD: + v = genIntegerAdd(x, y); + break; + case FADD: + case DADD: + v = genFloatAdd(x, y); + break; + case ISUB: + case LSUB: + v = genIntegerSub(x, y); + break; + case FSUB: + case DSUB: + v = genFloatSub(x, y); + break; + case IMUL: + case LMUL: + v = genIntegerMul(x, y); + break; + case FMUL: + case DMUL: + v = genFloatMul(x, y); + break; + case FDIV: + case DDIV: + v = genFloatDiv(x, y); + break; + case FREM: + case DREM: + v = genFloatRem(x, y); + break; + default: + throw new GraalInternalError("should not reach"); + } + frameState.push(result, append(v)); + } + + private void genIntegerDivOp(Kind result, int opcode) { + ValueNode y = frameState.pop(result); + ValueNode x = frameState.pop(result); + ValueNode v; + switch (opcode) { + case IDIV: + case LDIV: + v = genIntegerDiv(x, y); + break; + case IREM: + case LREM: + v = genIntegerRem(x, y); + break; + default: + throw new GraalInternalError("should not reach"); + } + frameState.push(result, append(v)); + } + + private void genNegateOp(Kind kind) { + frameState.push(kind, append(genNegateOp(frameState.pop(kind)))); + } + + private void genShiftOp(Kind kind, int opcode) { + ValueNode s = frameState.ipop(); + ValueNode x = frameState.pop(kind); + ValueNode v; + switch (opcode) { + case ISHL: + case LSHL: + v = genLeftShift(x, s); + break; + case ISHR: + case LSHR: + v = genRightShift(x, s); + break; + case IUSHR: + case LUSHR: + v = genUnsignedRightShift(x, s); + break; + default: + throw new GraalInternalError("should not reach"); + } + frameState.push(kind, append(v)); + } + + private void genLogicOp(Kind kind, int opcode) { + ValueNode y = frameState.pop(kind); + ValueNode x = frameState.pop(kind); + ValueNode v; + switch (opcode) { + case IAND: + case LAND: + v = genAnd(x, y); + break; + case IOR: + case LOR: + v = genOr(x, y); + break; + case IXOR: + case LXOR: + v = genXor(x, y); + break; + default: + throw new GraalInternalError("should not reach"); + } + frameState.push(kind, append(v)); + } + + private void genCompareOp(Kind kind, boolean isUnorderedLess) { + ValueNode y = frameState.pop(kind); + ValueNode x = frameState.pop(kind); + frameState.ipush(append(genNormalizeCompare(x, y, isUnorderedLess))); + } + + private void genFloatConvert(FloatConvert op, Kind from, Kind to) { + ValueNode input = frameState.pop(from.getStackKind()); + frameState.push(to.getStackKind(), append(genFloatConvert(op, input))); + } + + private void genSignExtend(Kind from, Kind to) { + ValueNode input = frameState.pop(from.getStackKind()); + if (from != from.getStackKind()) { + input = append(genNarrow(input, from.getBitCount())); + } + frameState.push(to.getStackKind(), append(genSignExtend(input, to.getBitCount()))); + } + + private void genZeroExtend(Kind from, Kind to) { + ValueNode input = frameState.pop(from.getStackKind()); + if (from != from.getStackKind()) { + input = append(genNarrow(input, from.getBitCount())); + } + frameState.push(to.getStackKind(), append(genZeroExtend(input, to.getBitCount()))); + } + + private void genNarrow(Kind from, Kind to) { + ValueNode input = frameState.pop(from.getStackKind()); + frameState.push(to.getStackKind(), append(genNarrow(input, to.getBitCount()))); + } + + private void genIncrement() { + int index = getStream().readLocalIndex(); + int delta = getStream().readIncrement(); + ValueNode x = frameState.loadLocal(index); + ValueNode y = appendConstant(JavaConstant.forInt(delta)); + frameState.storeLocal(index, append(genIntegerAdd(x, y))); + } + + private void genIfZero(Condition cond) { + ValueNode y = appendConstant(JavaConstant.INT_0); + ValueNode x = frameState.ipop(); + genIf(x, cond, y); + } + + private void genIfNull(Condition cond) { + ValueNode y = appendConstant(JavaConstant.NULL_POINTER); + ValueNode x = frameState.apop(); + genIf(x, cond, y); + } + + private void genIfSame(Kind kind, Condition cond) { + ValueNode y = frameState.pop(kind); + ValueNode x = frameState.pop(kind); + genIf(x, cond, y); + } + + protected JavaType lookupType(int cpi, int bytecode) { + maybeEagerlyResolve(cpi, bytecode); + JavaType result = constantPool.lookupType(cpi, bytecode); + assert !graphBuilderConfig.unresolvedIsError() || result instanceof ResolvedJavaType; + return result; + } + + private JavaMethod lookupMethod(int cpi, int opcode) { + maybeEagerlyResolve(cpi, opcode); + JavaMethod result = constantPool.lookupMethod(cpi, opcode); + /* + * In general, one cannot assume that the declaring class being initialized is + * useful, since the actual concrete receiver may be a different class (except for + * static calls). Also, interfaces are initialized only under special circumstances, + * so that this assertion would often fail for interface calls. + */ + assert !graphBuilderConfig.unresolvedIsError() || + (result instanceof ResolvedJavaMethod && (opcode != INVOKESTATIC || ((ResolvedJavaMethod) result).getDeclaringClass().isInitialized())) : result; + return result; + } + + private JavaField lookupField(int cpi, int opcode) { + maybeEagerlyResolve(cpi, opcode); + JavaField result = constantPool.lookupField(cpi, opcode); + assert !graphBuilderConfig.unresolvedIsError() || (result instanceof ResolvedJavaField && ((ResolvedJavaField) result).getDeclaringClass().isInitialized()) : result; + return result; + } + + private Object lookupConstant(int cpi, int opcode) { + maybeEagerlyResolve(cpi, opcode); + Object result = constantPool.lookupConstant(cpi); + assert !graphBuilderConfig.eagerResolving() || !(result instanceof JavaType) || (result instanceof ResolvedJavaType) : result; + return result; + } + + private void maybeEagerlyResolve(int cpi, int bytecode) { + if (graphBuilderConfig.eagerResolving() || intrinsicContext != null) { + constantPool.loadReferencedType(cpi, bytecode); + } + } + + private JavaTypeProfile getProfileForTypeCheck(ResolvedJavaType type) { + if (parsingIntrinsic() || profilingInfo == null || !optimisticOpts.useTypeCheckHints() || !canHaveSubtype(type)) { + return null; + } else { + return profilingInfo.getTypeProfile(bci()); + } + } + + private void genCheckCast() { + int cpi = getStream().readCPI(); + JavaType type = lookupType(cpi, CHECKCAST); + ValueNode object = frameState.apop(); + if (type instanceof ResolvedJavaType) { + ResolvedJavaType resolvedType = (ResolvedJavaType) type; + JavaTypeProfile profile = getProfileForTypeCheck(resolvedType); + TypeCheckPlugin typeCheckPlugin = this.graphBuilderConfig.getPlugins().getTypeCheckPlugin(); + if (typeCheckPlugin == null || !typeCheckPlugin.checkCast(this, object, resolvedType, profile)) { + ValueNode checkCastNode = append(createCheckCast(resolvedType, object, profile, false)); + frameState.apush(checkCastNode); + } + } else { + handleUnresolvedCheckCast(type, object); + } + } + + private void genInstanceOf() { + int cpi = getStream().readCPI(); + JavaType type = lookupType(cpi, INSTANCEOF); + ValueNode object = frameState.apop(); + if (type instanceof ResolvedJavaType) { + ResolvedJavaType resolvedType = (ResolvedJavaType) type; + JavaTypeProfile profile = getProfileForTypeCheck(resolvedType); + TypeCheckPlugin typeCheckPlugin = this.graphBuilderConfig.getPlugins().getTypeCheckPlugin(); + if (typeCheckPlugin == null || !typeCheckPlugin.instanceOf(this, object, resolvedType, profile)) { + ValueNode instanceOfNode = createInstanceOf(resolvedType, object, profile); + frameState.ipush(append(genConditional(genUnique(instanceOfNode)))); + } + } else { + handleUnresolvedInstanceOf(type, object); + } + } + + void genNewInstance(int cpi) { + JavaType type = lookupType(cpi, NEW); + if (type instanceof ResolvedJavaType && ((ResolvedJavaType) type).isInitialized()) { + ResolvedJavaType[] skippedExceptionTypes = this.graphBuilderConfig.getSkippedExceptionTypes(); + if (skippedExceptionTypes != null) { + for (ResolvedJavaType exceptionType : skippedExceptionTypes) { + if (exceptionType.isAssignableFrom((ResolvedJavaType) type)) { + append(new DeoptimizeNode(DeoptimizationAction.None, TransferToInterpreter)); + return; + } + } + } + frameState.apush(append(createNewInstance((ResolvedJavaType) type, true))); + } else { + handleUnresolvedNewInstance(type); + } + } + + private void genNewPrimitiveArray(int typeCode) { + Class clazz = arrayTypeCodeToClass(typeCode); + ResolvedJavaType elementType = metaAccess.lookupJavaType(clazz); + frameState.apush(append(createNewArray(elementType, frameState.ipop(), true))); + } + + private void genNewObjectArray(int cpi) { + JavaType type = lookupType(cpi, ANEWARRAY); + ValueNode length = frameState.ipop(); + if (type instanceof ResolvedJavaType) { + frameState.apush(append(createNewArray((ResolvedJavaType) type, length, true))); + } else { + handleUnresolvedNewObjectArray(type, length); + } + + } + + private void genNewMultiArray(int cpi) { + JavaType type = lookupType(cpi, MULTIANEWARRAY); + int rank = getStream().readUByte(bci() + 3); + List dims = new ArrayList<>(Collections.nCopies(rank, null)); + for (int i = rank - 1; i >= 0; i--) { + dims.set(i, frameState.ipop()); + } + if (type instanceof ResolvedJavaType) { + frameState.apush(append(createNewMultiArray((ResolvedJavaType) type, dims))); + } else { + handleUnresolvedNewMultiArray(type, dims); + } + } + + private void genGetField(JavaField field) { + Kind kind = field.getKind(); + ValueNode receiver = emitExplicitExceptions(frameState.apop(), null); + if ((field instanceof ResolvedJavaField) && ((ResolvedJavaField) field).getDeclaringClass().isInitialized()) { + LoadFieldPlugin loadFieldPlugin = this.graphBuilderConfig.getPlugins().getLoadFieldPlugin(); + if (loadFieldPlugin == null || !loadFieldPlugin.apply((GraphBuilderContext) this, receiver, (ResolvedJavaField) field)) { + appendOptimizedLoadField(kind, genLoadField(receiver, (ResolvedJavaField) field)); + } + } else { + handleUnresolvedLoadField(field, receiver); + } + } + + /** + * @param receiver the receiver of an object based operation + * @param index the index of an array based operation that is to be tested for out of + * bounds. This is null for a non-array operation. + * @return the receiver value possibly modified to have a tighter stamp + */ + protected ValueNode emitExplicitExceptions(ValueNode receiver, ValueNode index) { + assert receiver != null; + if (graphBuilderConfig.omitAllExceptionEdges() || + profilingInfo == null || + (optimisticOpts.useExceptionProbabilityForOperations() && profilingInfo.getExceptionSeen(bci()) == TriState.FALSE && !GraalOptions.StressExplicitExceptionCode.getValue())) { + return receiver; + } + + ValueNode nonNullReceiver = emitExplicitNullCheck(receiver); + if (index != null) { + ValueNode length = append(genArrayLength(nonNullReceiver)); + emitExplicitBoundsCheck(index, length); + } + EXPLICIT_EXCEPTIONS.increment(); + return nonNullReceiver; + } + + private void genPutField(JavaField field) { + ValueNode value = frameState.pop(field.getKind().getStackKind()); + ValueNode receiver = emitExplicitExceptions(frameState.apop(), null); + if (field instanceof ResolvedJavaField && ((ResolvedJavaField) field).getDeclaringClass().isInitialized()) { + genStoreField(receiver, (ResolvedJavaField) field, value); + } else { + handleUnresolvedStoreField(field, value, receiver); + } + } + + private void genGetStatic(JavaField field) { + Kind kind = field.getKind(); + if (field instanceof ResolvedJavaField && ((ResolvedJavaType) field.getDeclaringClass()).isInitialized()) { + LoadFieldPlugin loadFieldPlugin = this.graphBuilderConfig.getPlugins().getLoadFieldPlugin(); + if (loadFieldPlugin == null || !loadFieldPlugin.apply((GraphBuilderContext) this, (ResolvedJavaField) field)) { + appendOptimizedLoadField(kind, genLoadField(null, (ResolvedJavaField) field)); + } + } else { + handleUnresolvedLoadField(field, null); + } + } + + public boolean tryLoadFieldPlugin(JavaField field, LoadFieldPlugin loadFieldPlugin) { + return loadFieldPlugin.apply((GraphBuilderContext) this, (ResolvedJavaField) field); + } + + private void genPutStatic(JavaField field) { + ValueNode value = frameState.pop(field.getKind().getStackKind()); + if (field instanceof ResolvedJavaField && ((ResolvedJavaType) field.getDeclaringClass()).isInitialized()) { + genStoreField(null, (ResolvedJavaField) field, value); + } else { + handleUnresolvedStoreField(field, value, null); + } + } + + protected void appendOptimizedLoadField(Kind kind, ValueNode load) { + // append the load to the instruction + ValueNode optimized = append(load); + frameState.push(kind.getStackKind(), optimized); + } + + private double[] switchProbability(int numberOfCases, int bci) { + double[] prob = (profilingInfo == null ? null : profilingInfo.getSwitchProbabilities(bci)); + if (prob != null) { + assert prob.length == numberOfCases; + } else { + Debug.log("Missing probability (switch) in %s at bci %d", method, bci); + prob = new double[numberOfCases]; + for (int i = 0; i < numberOfCases; i++) { + prob[i] = 1.0d / numberOfCases; + } + } + assert allPositive(prob); + return prob; + } + + private void genSwitch(BytecodeSwitch bs) { + int bci = bci(); + ValueNode value = frameState.ipop(); + + int nofCases = bs.numberOfCases(); + double[] keyProbabilities = switchProbability(nofCases + 1, bci); + + Map bciToBlockSuccessorIndex = new HashMap<>(); + for (int i = 0; i < currentBlock.getSuccessorCount(); i++) { + assert !bciToBlockSuccessorIndex.containsKey(currentBlock.getSuccessor(i).startBci); + if (!bciToBlockSuccessorIndex.containsKey(currentBlock.getSuccessor(i).startBci)) { + bciToBlockSuccessorIndex.put(currentBlock.getSuccessor(i).startBci, new SuccessorInfo(i)); + } + } + + ArrayList actualSuccessors = new ArrayList<>(); + int[] keys = new int[nofCases]; + int[] keySuccessors = new int[nofCases + 1]; + int deoptSuccessorIndex = -1; + int nextSuccessorIndex = 0; + boolean constantValue = value.isConstant(); + for (int i = 0; i < nofCases + 1; i++) { + if (i < nofCases) { + keys[i] = bs.keyAt(i); + } + + if (!constantValue && isNeverExecutedCode(keyProbabilities[i])) { + if (deoptSuccessorIndex < 0) { + deoptSuccessorIndex = nextSuccessorIndex++; + actualSuccessors.add(null); + } + keySuccessors[i] = deoptSuccessorIndex; + } else { + int targetBci = i >= nofCases ? bs.defaultTarget() : bs.targetAt(i); + SuccessorInfo info = bciToBlockSuccessorIndex.get(targetBci); + if (info.actualIndex < 0) { + info.actualIndex = nextSuccessorIndex++; + actualSuccessors.add(currentBlock.getSuccessor(info.blockIndex)); + } + keySuccessors[i] = info.actualIndex; + } + } + + genIntegerSwitch(value, actualSuccessors, keys, keyProbabilities, keySuccessors); + + } + + protected boolean isNeverExecutedCode(double probability) { + return probability == 0 && optimisticOpts.removeNeverExecutedCode(); + } + + protected double branchProbability() { + if (profilingInfo == null) { + return 0.5; + } + assert assertAtIfBytecode(); + double probability = profilingInfo.getBranchTakenProbability(bci()); + if (probability < 0) { + assert probability == -1 : "invalid probability"; + Debug.log("missing probability in %s at bci %d", method, bci()); + probability = 0.5; + } + + if (!optimisticOpts.removeNeverExecutedCode()) { + if (probability == 0) { + probability = 0.0000001; + } else if (probability == 1) { + probability = 0.999999; + } + } + return probability; + } + + private boolean assertAtIfBytecode() { + int bytecode = stream.currentBC(); + switch (bytecode) { + case IFEQ: + case IFNE: + case IFLT: + case IFGE: + case IFGT: + case IFLE: + case IF_ICMPEQ: + case IF_ICMPNE: + case IF_ICMPLT: + case IF_ICMPGE: + case IF_ICMPGT: + case IF_ICMPLE: + case IF_ACMPEQ: + case IF_ACMPNE: + case IFNULL: + case IFNONNULL: + return true; + } + assert false : String.format("%x is not an if bytecode", bytecode); + return true; + } + + public final void processBytecode(int bci, int opcode) { + int cpi; + + // Checkstyle: stop + // @formatter:off + switch (opcode) { + case NOP : /* nothing to do */ break; + case ACONST_NULL : frameState.apush(appendConstant(JavaConstant.NULL_POINTER)); break; + case ICONST_M1 : // fall through + case ICONST_0 : // fall through + case ICONST_1 : // fall through + case ICONST_2 : // fall through + case ICONST_3 : // fall through + case ICONST_4 : // fall through + case ICONST_5 : frameState.ipush(appendConstant(JavaConstant.forInt(opcode - ICONST_0))); break; + case LCONST_0 : // fall through + case LCONST_1 : frameState.lpush(appendConstant(JavaConstant.forLong(opcode - LCONST_0))); break; + case FCONST_0 : // fall through + case FCONST_1 : // fall through + case FCONST_2 : frameState.fpush(appendConstant(JavaConstant.forFloat(opcode - FCONST_0))); break; + case DCONST_0 : // fall through + case DCONST_1 : frameState.dpush(appendConstant(JavaConstant.forDouble(opcode - DCONST_0))); break; + case BIPUSH : frameState.ipush(appendConstant(JavaConstant.forInt(stream.readByte()))); break; + case SIPUSH : frameState.ipush(appendConstant(JavaConstant.forInt(stream.readShort()))); break; + case LDC : // fall through + case LDC_W : // fall through + case LDC2_W : genLoadConstant(stream.readCPI(), opcode); break; + case ILOAD : loadLocal(stream.readLocalIndex(), Kind.Int); break; + case LLOAD : loadLocal(stream.readLocalIndex(), Kind.Long); break; + case FLOAD : loadLocal(stream.readLocalIndex(), Kind.Float); break; + case DLOAD : loadLocal(stream.readLocalIndex(), Kind.Double); break; + case ALOAD : loadLocal(stream.readLocalIndex(), Kind.Object); break; + case ILOAD_0 : // fall through + case ILOAD_1 : // fall through + case ILOAD_2 : // fall through + case ILOAD_3 : loadLocal(opcode - ILOAD_0, Kind.Int); break; + case LLOAD_0 : // fall through + case LLOAD_1 : // fall through + case LLOAD_2 : // fall through + case LLOAD_3 : loadLocal(opcode - LLOAD_0, Kind.Long); break; + case FLOAD_0 : // fall through + case FLOAD_1 : // fall through + case FLOAD_2 : // fall through + case FLOAD_3 : loadLocal(opcode - FLOAD_0, Kind.Float); break; + case DLOAD_0 : // fall through + case DLOAD_1 : // fall through + case DLOAD_2 : // fall through + case DLOAD_3 : loadLocal(opcode - DLOAD_0, Kind.Double); break; + case ALOAD_0 : // fall through + case ALOAD_1 : // fall through + case ALOAD_2 : // fall through + case ALOAD_3 : loadLocal(opcode - ALOAD_0, Kind.Object); break; + case IALOAD : genLoadIndexed(Kind.Int ); break; + case LALOAD : genLoadIndexed(Kind.Long ); break; + case FALOAD : genLoadIndexed(Kind.Float ); break; + case DALOAD : genLoadIndexed(Kind.Double); break; + case AALOAD : genLoadIndexed(Kind.Object); break; + case BALOAD : genLoadIndexed(Kind.Byte ); break; + case CALOAD : genLoadIndexed(Kind.Char ); break; + case SALOAD : genLoadIndexed(Kind.Short ); break; + case ISTORE : storeLocal(Kind.Int, stream.readLocalIndex()); break; + case LSTORE : storeLocal(Kind.Long, stream.readLocalIndex()); break; + case FSTORE : storeLocal(Kind.Float, stream.readLocalIndex()); break; + case DSTORE : storeLocal(Kind.Double, stream.readLocalIndex()); break; + case ASTORE : storeLocal(Kind.Object, stream.readLocalIndex()); break; + case ISTORE_0 : // fall through + case ISTORE_1 : // fall through + case ISTORE_2 : // fall through + case ISTORE_3 : storeLocal(Kind.Int, opcode - ISTORE_0); break; + case LSTORE_0 : // fall through + case LSTORE_1 : // fall through + case LSTORE_2 : // fall through + case LSTORE_3 : storeLocal(Kind.Long, opcode - LSTORE_0); break; + case FSTORE_0 : // fall through + case FSTORE_1 : // fall through + case FSTORE_2 : // fall through + case FSTORE_3 : storeLocal(Kind.Float, opcode - FSTORE_0); break; + case DSTORE_0 : // fall through + case DSTORE_1 : // fall through + case DSTORE_2 : // fall through + case DSTORE_3 : storeLocal(Kind.Double, opcode - DSTORE_0); break; + case ASTORE_0 : // fall through + case ASTORE_1 : // fall through + case ASTORE_2 : // fall through + case ASTORE_3 : storeLocal(Kind.Object, opcode - ASTORE_0); break; + case IASTORE : genStoreIndexed(Kind.Int ); break; + case LASTORE : genStoreIndexed(Kind.Long ); break; + case FASTORE : genStoreIndexed(Kind.Float ); break; + case DASTORE : genStoreIndexed(Kind.Double); break; + case AASTORE : genStoreIndexed(Kind.Object); break; + case BASTORE : genStoreIndexed(Kind.Byte ); break; + case CASTORE : genStoreIndexed(Kind.Char ); break; + case SASTORE : genStoreIndexed(Kind.Short ); break; + case POP : frameState.xpop(); break; + case POP2 : frameState.xpop(); frameState.xpop(); break; + case DUP : frameState.xpush(frameState.xpeek()); break; + case DUP_X1 : // fall through + case DUP_X2 : // fall through + case DUP2 : // fall through + case DUP2_X1 : // fall through + case DUP2_X2 : // fall through + case SWAP : stackOp(opcode); break; + case IADD : // fall through + case ISUB : // fall through + case IMUL : genArithmeticOp(Kind.Int, opcode); break; + case IDIV : // fall through + case IREM : genIntegerDivOp(Kind.Int, opcode); break; + case LADD : // fall through + case LSUB : // fall through + case LMUL : genArithmeticOp(Kind.Long, opcode); break; + case LDIV : // fall through + case LREM : genIntegerDivOp(Kind.Long, opcode); break; + case FADD : // fall through + case FSUB : // fall through + case FMUL : // fall through + case FDIV : // fall through + case FREM : genArithmeticOp(Kind.Float, opcode); break; + case DADD : // fall through + case DSUB : // fall through + case DMUL : // fall through + case DDIV : // fall through + case DREM : genArithmeticOp(Kind.Double, opcode); break; + case INEG : genNegateOp(Kind.Int); break; + case LNEG : genNegateOp(Kind.Long); break; + case FNEG : genNegateOp(Kind.Float); break; + case DNEG : genNegateOp(Kind.Double); break; + case ISHL : // fall through + case ISHR : // fall through + case IUSHR : genShiftOp(Kind.Int, opcode); break; + case IAND : // fall through + case IOR : // fall through + case IXOR : genLogicOp(Kind.Int, opcode); break; + case LSHL : // fall through + case LSHR : // fall through + case LUSHR : genShiftOp(Kind.Long, opcode); break; + case LAND : // fall through + case LOR : // fall through + case LXOR : genLogicOp(Kind.Long, opcode); break; + case IINC : genIncrement(); break; + case I2F : genFloatConvert(FloatConvert.I2F, Kind.Int, Kind.Float); break; + case I2D : genFloatConvert(FloatConvert.I2D, Kind.Int, Kind.Double); break; + case L2F : genFloatConvert(FloatConvert.L2F, Kind.Long, Kind.Float); break; + case L2D : genFloatConvert(FloatConvert.L2D, Kind.Long, Kind.Double); break; + case F2I : genFloatConvert(FloatConvert.F2I, Kind.Float, Kind.Int); break; + case F2L : genFloatConvert(FloatConvert.F2L, Kind.Float, Kind.Long); break; + case F2D : genFloatConvert(FloatConvert.F2D, Kind.Float, Kind.Double); break; + case D2I : genFloatConvert(FloatConvert.D2I, Kind.Double, Kind.Int); break; + case D2L : genFloatConvert(FloatConvert.D2L, Kind.Double, Kind.Long); break; + case D2F : genFloatConvert(FloatConvert.D2F, Kind.Double, Kind.Float); break; + case L2I : genNarrow(Kind.Long, Kind.Int); break; + case I2L : genSignExtend(Kind.Int, Kind.Long); break; + case I2B : genSignExtend(Kind.Byte, Kind.Int); break; + case I2S : genSignExtend(Kind.Short, Kind.Int); break; + case I2C : genZeroExtend(Kind.Char, Kind.Int); break; + case LCMP : genCompareOp(Kind.Long, false); break; + case FCMPL : genCompareOp(Kind.Float, true); break; + case FCMPG : genCompareOp(Kind.Float, false); break; + case DCMPL : genCompareOp(Kind.Double, true); break; + case DCMPG : genCompareOp(Kind.Double, false); break; + case IFEQ : genIfZero(Condition.EQ); break; + case IFNE : genIfZero(Condition.NE); break; + case IFLT : genIfZero(Condition.LT); break; + case IFGE : genIfZero(Condition.GE); break; + case IFGT : genIfZero(Condition.GT); break; + case IFLE : genIfZero(Condition.LE); break; + case IF_ICMPEQ : genIfSame(Kind.Int, Condition.EQ); break; + case IF_ICMPNE : genIfSame(Kind.Int, Condition.NE); break; + case IF_ICMPLT : genIfSame(Kind.Int, Condition.LT); break; + case IF_ICMPGE : genIfSame(Kind.Int, Condition.GE); break; + case IF_ICMPGT : genIfSame(Kind.Int, Condition.GT); break; + case IF_ICMPLE : genIfSame(Kind.Int, Condition.LE); break; + case IF_ACMPEQ : genIfSame(Kind.Object, Condition.EQ); break; + case IF_ACMPNE : genIfSame(Kind.Object, Condition.NE); break; + case GOTO : genGoto(); break; + case JSR : genJsr(stream.readBranchDest()); break; + case RET : genRet(stream.readLocalIndex()); break; + case TABLESWITCH : genSwitch(new BytecodeTableSwitch(getStream(), bci())); break; + case LOOKUPSWITCH : genSwitch(new BytecodeLookupSwitch(getStream(), bci())); break; + case IRETURN : genReturn(frameState.ipop(), Kind.Int); break; + case LRETURN : genReturn(frameState.lpop(), Kind.Long); break; + case FRETURN : genReturn(frameState.fpop(), Kind.Float); break; + case DRETURN : genReturn(frameState.dpop(), Kind.Double); break; + case ARETURN : genReturn(frameState.apop(), Kind.Object); break; + case RETURN : genReturn(null, Kind.Void); break; + case GETSTATIC : cpi = stream.readCPI(); genGetStatic(lookupField(cpi, opcode)); break; + case PUTSTATIC : cpi = stream.readCPI(); genPutStatic(lookupField(cpi, opcode)); break; + case GETFIELD : cpi = stream.readCPI(); genGetField(lookupField(cpi, opcode)); break; + case PUTFIELD : cpi = stream.readCPI(); genPutField(lookupField(cpi, opcode)); break; + case INVOKEVIRTUAL : cpi = stream.readCPI(); genInvokeVirtual(lookupMethod(cpi, opcode)); break; + case INVOKESPECIAL : cpi = stream.readCPI(); genInvokeSpecial(lookupMethod(cpi, opcode)); break; + case INVOKESTATIC : cpi = stream.readCPI(); genInvokeStatic(lookupMethod(cpi, opcode)); break; + case INVOKEINTERFACE: cpi = stream.readCPI(); genInvokeInterface(lookupMethod(cpi, opcode)); break; + case INVOKEDYNAMIC : cpi = stream.readCPI4(); genInvokeDynamic(lookupMethod(cpi, opcode)); break; + case NEW : genNewInstance(stream.readCPI()); break; + case NEWARRAY : genNewPrimitiveArray(stream.readLocalIndex()); break; + case ANEWARRAY : genNewObjectArray(stream.readCPI()); break; + case ARRAYLENGTH : genArrayLength(); break; + case ATHROW : genThrow(); break; + case CHECKCAST : genCheckCast(); break; + case INSTANCEOF : genInstanceOf(); break; + case MONITORENTER : genMonitorEnter(frameState.apop(), stream.nextBCI()); break; + case MONITOREXIT : genMonitorExit(frameState.apop(), null, stream.nextBCI()); break; + case MULTIANEWARRAY : genNewMultiArray(stream.readCPI()); break; + case IFNULL : genIfNull(Condition.EQ); break; + case IFNONNULL : genIfNull(Condition.NE); break; + case GOTO_W : genGoto(); break; + case JSR_W : genJsr(stream.readBranchDest()); break; + case BREAKPOINT: + throw new BailoutException("concurrent setting of breakpoint"); + default: + throw new BailoutException("Unsupported opcode %d (%s) [bci=%d]", opcode, nameOf(opcode), bci); + } + // @formatter:on + // Checkstyle: resume + } + + private void genArrayLength() { + frameState.ipush(append(genArrayLength(frameState.apop()))); + } + + public ResolvedJavaMethod getMethod() { + return method; + } + + public HIRFrameStateBuilder getFrameState() { + return frameState; + } + + protected boolean traceInstruction(int bci, int opcode, boolean blockStart) { + if (Debug.isEnabled() && Options.TraceBytecodeParserLevel.getValue() >= TRACELEVEL_INSTRUCTIONS && Debug.isLogEnabled()) { + traceInstructionHelper(bci, opcode, blockStart); + } + return true; + } + + private void traceInstructionHelper(int bci, int opcode, boolean blockStart) { + StringBuilder sb = new StringBuilder(40); + sb.append(blockStart ? '+' : '|'); + if (bci < 10) { + sb.append(" "); + } else if (bci < 100) { + sb.append(' '); + } + sb.append(bci).append(": ").append(Bytecodes.nameOf(opcode)); + for (int i = bci + 1; i < stream.nextBCI(); ++i) { + sb.append(' ').append(stream.readUByte(i)); + } + if (!currentBlock.getJsrScope().isEmpty()) { + sb.append(' ').append(currentBlock.getJsrScope()); + } + Debug.log("%s", sb); + } + + public boolean parsingIntrinsic() { + return intrinsicContext != null; + } } } diff -r e34bc00733d1 -r acfc5e32e678 graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java Tue May 12 17:29:49 2015 -0700 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/HIRFrameStateBuilder.java Tue May 12 18:04:53 2015 -0700 @@ -23,6 +23,7 @@ package com.oracle.graal.java; import static com.oracle.graal.graph.iterators.NodePredicates.*; +import static com.oracle.graal.java.GraphBuilderPhase.Options.*; import java.util.*; @@ -31,8 +32,8 @@ import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; +import com.oracle.graal.graphbuilderconf.IntrinsicContext.SideEffectsState; import com.oracle.graal.graphbuilderconf.*; -import com.oracle.graal.graphbuilderconf.IntrinsicContext.*; import com.oracle.graal.java.BciBlockMapping.BciBlock; import com.oracle.graal.java.GraphBuilderPhase.Instance.BytecodeParser; import com.oracle.graal.nodeinfo.*; @@ -227,7 +228,7 @@ public BytecodePosition createBytecodePosition(int bci) { BytecodeParser parent = parser.getParent(); - if (AbstractBytecodeParser.Options.HideSubstitutionStates.getValue()) { + if (HideSubstitutionStates.getValue()) { if (parser.parsingIntrinsic()) { // Attribute to the method being replaced return new BytecodePosition(parent.getFrameState().createBytecodePosition(parent.bci()), parser.intrinsicContext.getOriginalMethod(), -1); diff -r e34bc00733d1 -r acfc5e32e678 graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java --- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java Tue May 12 17:29:49 2015 -0700 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMove.java Tue May 12 18:04:53 2015 -0700 @@ -343,10 +343,16 @@ public static final LIRInstructionClass TYPE = LIRInstructionClass.create(LoadOp.class); @Def({REG}) protected AllocatableValue result; + protected boolean signExtend; public LoadOp(Kind kind, AllocatableValue result, SPARCAddressValue address, LIRFrameState state) { + this(kind, result, address, state, false); + } + + public LoadOp(Kind kind, AllocatableValue result, SPARCAddressValue address, LIRFrameState state, boolean signExtend) { super(TYPE, kind, address, state); this.result = result; + this.signExtend = signExtend; } @Override @@ -362,16 +368,28 @@ switch ((Kind) kind) { case Boolean: case Byte: - masm.ldsb(addr, dst); + if (signExtend) { + masm.ldsb(addr, dst); + } else { + masm.ldub(addr, dst); + } break; case Short: - masm.ldsh(addr, dst); + if (signExtend) { + masm.ldsh(addr, dst); + } else { + masm.lduh(addr, dst); + } break; case Char: masm.lduh(addr, dst); break; case Int: - masm.ldsw(addr, dst); + if (signExtend) { + masm.ldsw(addr, dst); + } else { + masm.lduw(addr, dst); + } break; case Long: masm.ldx(addr, dst); diff -r e34bc00733d1 -r acfc5e32e678 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java Tue May 12 17:29:49 2015 -0700 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java Tue May 12 18:04:53 2015 -0700 @@ -412,4 +412,23 @@ test("arrayCopyTypeName", (Object) new Object[]{"one", "two", "three"}); test("arrayCopyTypeName", (Object) new String[]{"one", "two", "three"}); } + + public int conditionalInstantiation(Object o) { + int total = 0; + if (o instanceof CharSequence) { + if (o instanceof StringBuilder || o instanceof String) { + total = 9; + } + total += (o instanceof String ? 2 : 1); + } + + return total; + } + + @Test + public void testInstantiation() { + test("conditionalInstantiation", "foo"); + test("conditionalInstantiation", new StringBuilder()); + test("conditionalInstantiation", 1); + } } diff -r e34bc00733d1 -r acfc5e32e678 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultInlineInvokePlugin.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultInlineInvokePlugin.java Tue May 12 17:29:49 2015 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultInlineInvokePlugin.java Tue May 12 18:04:53 2015 -0700 @@ -23,7 +23,7 @@ package com.oracle.graal.replacements; import static com.oracle.graal.compiler.common.GraalOptions.*; -import static com.oracle.graal.java.AbstractBytecodeParser.Options.*; +import static com.oracle.graal.java.GraphBuilderPhase.Options.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graphbuilderconf.*; diff -r e34bc00733d1 -r acfc5e32e678 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java Tue May 12 17:29:49 2015 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java Tue May 12 18:04:53 2015 -0700 @@ -96,7 +96,17 @@ protected InstanceOfUsageReplacer createReplacer(FloatingNode instanceOf, Instantiation instantiation, Node usage, final StructuredGraph graph) { InstanceOfUsageReplacer replacer; if (usage instanceof IfNode || usage instanceof FixedGuardNode || usage instanceof ShortCircuitOrNode || usage instanceof GuardingPiNode || usage instanceof ConditionAnchorNode) { - replacer = new NonMaterializationUsageReplacer(instantiation, ConstantNode.forInt(1, graph), ConstantNode.forInt(0, graph), instanceOf, usage); + ValueNode trueValue = ConstantNode.forInt(1, graph); + ValueNode falseValue = ConstantNode.forInt(0, graph); + if (instantiation.isInitialized() && (trueValue != instantiation.trueValue || falseValue != instantiation.falseValue)) { + /* + * This code doesn't really care what values are used so adopt the values from the + * previous instantiation. + */ + trueValue = instantiation.trueValue; + falseValue = instantiation.falseValue; + } + replacer = new NonMaterializationUsageReplacer(instantiation, trueValue, falseValue, instanceOf, usage); } else { assert usage instanceof ConditionalNode : "unexpected usage of " + instanceOf + ": " + usage; ConditionalNode c = (ConditionalNode) usage; diff -r e34bc00733d1 -r acfc5e32e678 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/PEGraphDecoder.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/PEGraphDecoder.java Tue May 12 17:29:49 2015 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/PEGraphDecoder.java Tue May 12 18:04:53 2015 -0700 @@ -23,7 +23,7 @@ package com.oracle.graal.replacements; import static com.oracle.graal.compiler.common.GraalInternalError.*; -import static com.oracle.graal.java.AbstractBytecodeParser.Options.*; +import static com.oracle.graal.java.GraphBuilderPhase.Options.*; import java.util.*; diff -r e34bc00733d1 -r acfc5e32e678 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Tue May 12 17:29:49 2015 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Tue May 12 18:04:53 2015 -0700 @@ -25,7 +25,7 @@ import static com.oracle.graal.api.meta.MetaUtil.*; import static com.oracle.graal.compiler.common.GraalOptions.*; import static com.oracle.graal.graphbuilderconf.IntrinsicContext.CompilationContext.*; -import static com.oracle.graal.java.AbstractBytecodeParser.Options.*; +import static com.oracle.graal.java.GraphBuilderPhase.Options.*; import static com.oracle.graal.phases.common.DeadCodeEliminationPhase.Optionality.*; import static java.lang.String.*; diff -r e34bc00733d1 -r acfc5e32e678 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Tue May 12 17:29:49 2015 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Tue May 12 18:04:53 2015 -0700 @@ -23,7 +23,7 @@ package com.oracle.graal.truffle; import static com.oracle.graal.compiler.common.GraalOptions.*; -import static com.oracle.graal.java.AbstractBytecodeParser.Options.*; +import static com.oracle.graal.java.GraphBuilderPhase.Options.*; import static com.oracle.graal.truffle.TruffleCompilerOptions.*; import java.lang.invoke.*; diff -r e34bc00733d1 -r acfc5e32e678 src/share/vm/runtime/arguments.cpp --- a/src/share/vm/runtime/arguments.cpp Tue May 12 17:29:49 2015 -0700 +++ b/src/share/vm/runtime/arguments.cpp Tue May 12 18:04:53 2015 -0700 @@ -1502,9 +1502,6 @@ // to use UseCompressedOops is InitialHeapSize. size_t max_heap_size = MAX2(MaxHeapSize, InitialHeapSize); // Set default on graal with sparc to not use compressed oops as long they are not implemented -/*#if defined(GRAAL) && defined(TARGET_ARCH_sparc) - FLAG_SET_DEFAULT(UseCompressedOops, false); -#else // if !(GRAAL && SOLARIS)*/ if (max_heap_size <= max_heap_for_compressed_oops()) { #if !defined(COMPILER1) || defined(TIERED) if (FLAG_IS_DEFAULT(UseCompressedOops)) { @@ -1529,7 +1526,6 @@ } #endif // _LP64 #endif // ZERO -//#endif // !(GRAAL && SOLARIS) }