< prev index next >

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java

Print this page

        

*** 1,7 **** /* ! * Copyright (c) 2009, 2019, 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. --- 1,7 ---- /* ! * Copyright (c) 2009, 2018, 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.
*** 36,45 **** --- 36,46 ---- import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint; import static jdk.vm.ci.meta.DeoptimizationReason.TypeCheckedInliningViolated; import static jdk.vm.ci.meta.DeoptimizationReason.UnreachedCode; import static jdk.vm.ci.meta.DeoptimizationReason.Unresolved; import static jdk.vm.ci.runtime.JVMCICompiler.INVOCATION_ENTRY_BCI; + import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE; import static org.graalvm.compiler.bytecode.Bytecodes.AALOAD; import static org.graalvm.compiler.bytecode.Bytecodes.AASTORE; import static org.graalvm.compiler.bytecode.Bytecodes.ACONST_NULL; import static org.graalvm.compiler.bytecode.Bytecodes.ALOAD; import static org.graalvm.compiler.bytecode.Bytecodes.ALOAD_0;
*** 268,277 **** --- 269,279 ---- import java.util.List; import java.util.function.Supplier; import jdk.internal.vm.compiler.collections.EconomicMap; import jdk.internal.vm.compiler.collections.Equivalence; + import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.bytecode.Bytecode; import org.graalvm.compiler.bytecode.BytecodeDisassembler; import org.graalvm.compiler.bytecode.BytecodeLookupSwitch; import org.graalvm.compiler.bytecode.BytecodeProvider;
*** 422,432 **** import org.graalvm.compiler.nodes.type.StampTool; import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.util.ValueMergeUtil; ! import org.graalvm.compiler.serviceprovider.GraalServices; import jdk.internal.vm.compiler.word.LocationIdentity; import jdk.vm.ci.code.BailoutException; import jdk.vm.ci.code.BytecodeFrame; import jdk.vm.ci.code.CodeUtil; --- 424,434 ---- import org.graalvm.compiler.nodes.type.StampTool; import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.util.ValueMergeUtil; ! import org.graalvm.compiler.serviceprovider.JavaVersionUtil; import jdk.internal.vm.compiler.word.LocationIdentity; import jdk.vm.ci.code.BailoutException; import jdk.vm.ci.code.BytecodeFrame; import jdk.vm.ci.code.CodeUtil;
*** 1288,1299 **** protected LogicNode genUnique(LogicNode x) { return graph.addOrUniqueWithInputs(x); } ! protected ValueNode genIfNode(LogicNode condition, FixedNode falseSuccessor, FixedNode trueSuccessor, double d) { ! return new IfNode(condition, falseSuccessor, trueSuccessor, d); } protected void genThrow() { genInfoPointNode(InfopointReason.BYTECODE_POSITION, null); --- 1290,1301 ---- protected LogicNode genUnique(LogicNode x) { return graph.addOrUniqueWithInputs(x); } ! protected ValueNode genIfNode(LogicNode condition, FixedNode trueSuccessor, FixedNode falseSuccessor, double d) { ! return new IfNode(condition, trueSuccessor, falseSuccessor, d); } protected void genThrow() { genInfoPointNode(InfopointReason.BYTECODE_POSITION, null);
*** 1644,1658 **** } private boolean forceInliningEverything; @Override ! public void handleReplacedInvoke(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args, boolean inlineEverything) { boolean previous = forceInliningEverything; forceInliningEverything = previous || inlineEverything; try { ! appendInvoke(invokeKind, targetMethod, args); } finally { forceInliningEverything = previous; } } --- 1646,1660 ---- } private boolean forceInliningEverything; @Override ! public Invoke handleReplacedInvoke(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args, boolean inlineEverything) { boolean previous = forceInliningEverything; forceInliningEverything = previous || inlineEverything; try { ! return appendInvoke(invokeKind, targetMethod, args); } finally { forceInliningEverything = previous; } }
*** 1718,1728 **** } return null; } } if (invokeKind.isDirect()) { - inlineInfo = tryInline(args, targetMethod); if (inlineInfo == SUCCESSFULLY_INLINED) { return null; } } --- 1720,1729 ----
*** 2318,2328 **** if (scope != null) { graph.getInliningLog().addDecision(scope.getInvoke(), false, "GraphBuilderPhase", null, null, "native method"); } return false; } ! if (canInlinePartialIntrinsicExit() && InlinePartialIntrinsicExitDuringParsing.getValue(options)) { // Otherwise inline the original method. Any frame state created // during the inlining will exclude frame(s) in the // intrinsic method (see FrameStateBuilder.create(int bci)). notifyBeforeInline(inlinedMethod); printInlining(targetMethod, inlinedMethod, true, "partial intrinsic exit (bytecode parsing)"); --- 2319,2329 ---- if (scope != null) { graph.getInliningLog().addDecision(scope.getInvoke(), false, "GraphBuilderPhase", null, null, "native method"); } return false; } ! if (canInlinePartialIntrinsicExit() && InlinePartialIntrinsicExitDuringParsing.getValue(options) && !IS_BUILDING_NATIVE_IMAGE) { // Otherwise inline the original method. Any frame state created // during the inlining will exclude frame(s) in the // intrinsic method (see FrameStateBuilder.create(int bci)). notifyBeforeInline(inlinedMethod); printInlining(targetMethod, inlinedMethod, true, "partial intrinsic exit (bytecode parsing)");
*** 2538,2556 **** return invoke; } protected void genReturn(ValueNode returnVal, JavaKind returnKind) { if (parsingIntrinsic() && returnVal != null) { if (returnVal instanceof StateSplit) { StateSplit stateSplit = (StateSplit) returnVal; FrameState stateAfter = stateSplit.stateAfter(); if (stateSplit.hasSideEffect()) { assert stateSplit != null; if (stateAfter.bci == BytecodeFrame.AFTER_BCI) { assert stateAfter.usages().count() == 1; assert stateAfter.usages().first() == stateSplit; ! stateAfter.replaceAtUsages(graph.add(new FrameState(BytecodeFrame.AFTER_BCI, returnVal))); GraphUtil.killWithUnusedFloatingInputs(stateAfter); } else { /* * This must be the return value from within a partial intrinsification. */ --- 2539,2571 ---- return invoke; } protected void genReturn(ValueNode returnVal, JavaKind returnKind) { if (parsingIntrinsic() && returnVal != null) { + if (returnVal instanceof StateSplit) { StateSplit stateSplit = (StateSplit) returnVal; FrameState stateAfter = stateSplit.stateAfter(); if (stateSplit.hasSideEffect()) { assert stateSplit != null; if (stateAfter.bci == BytecodeFrame.AFTER_BCI) { assert stateAfter.usages().count() == 1; assert stateAfter.usages().first() == stateSplit; ! FrameState state; ! if (returnVal.getStackKind() == JavaKind.Illegal) { ! // This should only occur when Fold and NodeIntrinsic plugins are ! // deferred. Their return value might not be a Java type and in that ! // case this can't be the final AFTER_BCI so just create a FrameState ! // without a return value on the top of stack. ! assert stateSplit instanceof Invoke; ! ResolvedJavaMethod targetMethod = ((Invoke) stateSplit).getTargetMethod(); ! assert targetMethod != null && (targetMethod.getAnnotation(Fold.class) != null || targetMethod.getAnnotation(Node.NodeIntrinsic.class) != null); ! state = new FrameState(BytecodeFrame.AFTER_BCI); ! } else { ! state = new FrameState(BytecodeFrame.AFTER_BCI, returnVal); ! } ! stateAfter.replaceAtUsages(graph.add(state)); GraphUtil.killWithUnusedFloatingInputs(stateAfter); } else { /* * This must be the return value from within a partial intrinsification. */
*** 3393,3422 **** } else { if (condition.graph() == null) { condition = genUnique(condition); } ! NodeSourcePosition currentPosition = graph.currentNodeSourcePosition(); if (isNeverExecutedCode(probability)) { ! NodeSourcePosition survivingSuccessorPosition = graph.trackNodeSourcePosition() ! ? new NodeSourcePosition(currentPosition.getCaller(), currentPosition.getMethod(), falseBlock.startBci) ! : null; ! append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, true, survivingSuccessorPosition)); ! if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) { ! profilingPlugin.profileGoto(this, method, bci(), falseBlock.startBci, stateBefore); ! } ! appendGoto(falseBlock); ! return; } else if (isNeverExecutedCode(1 - probability)) { ! NodeSourcePosition survivingSuccessorPosition = graph.trackNodeSourcePosition() ! ? new NodeSourcePosition(currentPosition.getCaller(), currentPosition.getMethod(), trueBlock.startBci) ! : null; ! append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, false, survivingSuccessorPosition)); ! if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) { ! profilingPlugin.profileGoto(this, method, bci(), trueBlock.startBci, stateBefore); } - appendGoto(trueBlock); return; } if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) { profilingPlugin.profileIf(this, method, bci(), condition, trueBlock.startBci, falseBlock.startBci, stateBefore); --- 3408,3455 ---- } else { if (condition.graph() == null) { condition = genUnique(condition); } ! BciBlock deoptBlock = null; ! BciBlock noDeoptBlock = null; if (isNeverExecutedCode(probability)) { ! deoptBlock = trueBlock; ! noDeoptBlock = falseBlock; } else if (isNeverExecutedCode(1 - probability)) { ! deoptBlock = falseBlock; ! noDeoptBlock = trueBlock; ! } ! ! if (deoptBlock != null) { ! NodeSourcePosition currentPosition = graph.currentNodeSourcePosition(); ! NodeSourcePosition survivingSuccessorPosition = null; ! if (graph.trackNodeSourcePosition()) { ! survivingSuccessorPosition = new NodeSourcePosition(currentPosition.getCaller(), currentPosition.getMethod(), noDeoptBlock.startBci); ! } ! boolean negated = deoptBlock == trueBlock; ! if (!isPotentialCountedLoopExit(condition, deoptBlock)) { ! if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) { ! profilingPlugin.profileGoto(this, method, bci(), noDeoptBlock.startBci, stateBefore); ! } ! append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, negated, survivingSuccessorPosition)); ! appendGoto(noDeoptBlock); ! } else { ! this.controlFlowSplit = true; ! FixedNode noDeoptSuccessor = createTarget(noDeoptBlock, frameState, false, true); ! DeoptimizeNode deopt = graph.add(new DeoptimizeNode(InvalidateReprofile, UnreachedCode)); ! /* ! * We do not want to `checkLoopExit` here: otherwise the deopt will go to the ! * deoptBlock's BCI, skipping the branch in the interpreter, and the profile ! * will never see that the branch is taken. This can lead to deopt loops or OSR ! * failure. ! */ ! FixedNode deoptSuccessor = BeginNode.begin(deopt); ! ValueNode ifNode = genIfNode(condition, negated ? deoptSuccessor : noDeoptSuccessor, negated ? noDeoptSuccessor : deoptSuccessor, negated ? 1 - probability : probability); ! postProcessIfNode(ifNode); ! append(ifNode); } return; } if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) { profilingPlugin.profileIf(this, method, bci(), condition, trueBlock.startBci, falseBlock.startBci, stateBefore);
*** 3440,3449 **** --- 3473,3492 ---- postProcessIfNode(ifNode); append(ifNode); } } + public boolean isPotentialCountedLoopExit(LogicNode condition, BciBlock target) { + if (currentBlock != null) { + long exits = currentBlock.loops & ~target.loops; + if (exits != 0) { + return condition instanceof CompareNode; + } + } + return false; + } + /** * Hook for subclasses to decide whether the IfNode probability should be complemented during * conversion to Graal IR. */ protected boolean shouldComplementProbability() {
*** 3951,3961 **** return result; } private String unresolvedMethodAssertionMessage(JavaMethod result) { String message = result.format("%H.%n(%P)%R"); ! if (GraalServices.Java8OrEarlier) { JavaType declaringClass = result.getDeclaringClass(); String className = declaringClass.getName(); switch (className) { case "Ljava/nio/ByteBuffer;": case "Ljava/nio/ShortBuffer;": --- 3994,4004 ---- return result; } private String unresolvedMethodAssertionMessage(JavaMethod result) { String message = result.format("%H.%n(%P)%R"); ! if (JavaVersionUtil.Java8OrEarlier) { JavaType declaringClass = result.getDeclaringClass(); String className = declaringClass.getName(); switch (className) { case "Ljava/nio/ByteBuffer;": case "Ljava/nio/ShortBuffer;":
*** 4212,4228 **** if (!resolvedType.isInitialized() && classInitializationPlugin == null) { handleIllegalNewInstance(resolvedType); return; } ! ResolvedJavaType[] skippedExceptionTypes = this.graphBuilderConfig.getSkippedExceptionTypes(); ! if (skippedExceptionTypes != null) { ! for (ResolvedJavaType exceptionType : skippedExceptionTypes) { ! if (exceptionType.isAssignableFrom(resolvedType)) { ! append(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, RuntimeConstraint)); ! return; ! } } } if (classInitializationPlugin != null) { classInitializationPlugin.apply(this, resolvedType, this::createCurrentFrameState); --- 4255,4268 ---- if (!resolvedType.isInitialized() && classInitializationPlugin == null) { handleIllegalNewInstance(resolvedType); return; } ! for (ResolvedJavaType exceptionType : this.graphBuilderConfig.getSkippedExceptionTypes()) { ! if (exceptionType.isAssignableFrom(resolvedType)) { ! append(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, RuntimeConstraint)); ! return; } } if (classInitializationPlugin != null) { classInitializationPlugin.apply(this, resolvedType, this::createCurrentFrameState);
*** 4511,4523 **** /* * Javac does not allow use of "$assertionsDisabled" for a field name but Eclipse does, in * which case a suffix is added to the generated field. */ ! if ((parsingIntrinsic() || graphBuilderConfig.omitAssertions()) && resolvedField.isSynthetic() && resolvedField.getName().startsWith("$assertionsDisabled")) { ! frameState.push(field.getJavaKind(), ConstantNode.forBoolean(true, graph)); ! return; } ResolvedJavaType holder = resolvedField.getDeclaringClass(); ClassInitializationPlugin classInitializationPlugin = this.graphBuilderConfig.getPlugins().getClassInitializationPlugin(); if (classInitializationPlugin != null) { --- 4551,4567 ---- /* * Javac does not allow use of "$assertionsDisabled" for a field name but Eclipse does, in * which case a suffix is added to the generated field. */ ! if (resolvedField.isSynthetic() && resolvedField.getName().startsWith("$assertionsDisabled")) { ! if (parsingIntrinsic()) { ! throw new GraalError("Cannot use an assertion within the context of an intrinsic."); ! } else if (graphBuilderConfig.omitAssertions()) { ! frameState.push(field.getJavaKind(), ConstantNode.forBoolean(true, graph)); ! return; ! } } ResolvedJavaType holder = resolvedField.getDeclaringClass(); ClassInitializationPlugin classInitializationPlugin = this.graphBuilderConfig.getPlugins().getClassInitializationPlugin(); if (classInitializationPlugin != null) {
< prev index next >