private static boolean checkInliningDepth(GraphBuilderContext b) { int nodeCount = b.getGraph().getNodeCount(); int maxDepth = InlineDuringParsingMaxDepth.getValue(b.getOptions()); if (nodeCount > NodeBudget && MaxDepthAfterBudgetExceeded < maxDepth) { maxDepth = MaxDepthAfterBudgetExceeded; } return b.getDepth() < maxDepth; }
@Override public boolean handleLoadStaticField(GraphBuilderContext b, ResolvedJavaField field) { if (!ImmutableCode.getValue(b.getOptions()) || b.parsingIntrinsic()) { if (tryReadField(b, field, null)) { return true; } } if (b.parsingIntrinsic() && wordOperationPlugin.handleLoadStaticField(b, field)) { return true; } return false; }
/** * Determines whether a given method should be inlined based on whether it has a substitution or * whether the inlining context is already within a substitution. * * @return an object specifying how {@code method} is to be inlined or null if it should not be * inlined based on substitution related criteria */ @Override public InlineInfo shouldInlineInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) { Bytecode subst = getSubstitutionBytecode(method); if (subst != null) { if (b.parsingIntrinsic() || InlineDuringParsing.getValue(b.getOptions()) || InlineIntrinsicsDuringParsing.getValue(b.getOptions())) { // Forced inlining of intrinsics return createIntrinsicInlineInfo(subst.getMethod(), method, subst.getOrigin()); } return null; } if (b.parsingIntrinsic()) { assert b.getDepth() < MAX_GRAPH_INLINING_DEPTH : "inlining limit exceeded"; // Force inlining when parsing replacements return createIntrinsicInlineInfo(method, null, defaultBytecodeProvider); } else { assert IS_BUILDING_NATIVE_IMAGE || method.getAnnotation(NodeIntrinsic.class) == null : String.format("@%s method %s must only be called from within a replacement%n%s", NodeIntrinsic.class.getSimpleName(), method.format("%h.%n"), b); } return null; }
@Override public void profileGoto(GraphBuilderContext builder, ResolvedJavaMethod method, int bci, int targetBci, FrameState frameState) { assert shouldProfile(builder, method); OptionValues options = builder.getOptions(); if (Options.ProfileBackedges.getValue(options) && targetBci <= bci) { ProfileNode p = builder.append(new ProfileBranchNode(method, backedgeNotifyFreqLog(options), backedgeProfilePobabilityLog(options), bci, targetBci)); p.setStateBefore(frameState); } }
@Override public void checkNewNodes(GraphBuilderContext b, InvocationPlugin plugin, NodeIterable<Node> newNodes) { for (Node node : newNodes) { if (node instanceof MacroNode) { // MacroNode based plugins can only be used for inlining since they // require a valid bci should they need to replace themselves with // an InvokeNode during lowering. assert plugin.inlineOnly() : String.format("plugin that creates a %s (%s) must return true for inlineOnly(): %s", MacroNode.class.getSimpleName(), node, plugin); } } if (GraalOptions.ImmutableCode.getValue(b.getOptions())) { for (Node node : newNodes) { if (node.hasUsages() && node instanceof ConstantNode) { ConstantNode c = (ConstantNode) node; if (c.getStackKind() == JavaKind.Object && AheadOfTimeVerificationPhase.isIllegalObjectConstant(c)) { if (isClass(c)) { // This will be handled later by LoadJavaMirrorWithKlassPhase } else { // Tolerate uses in unused FrameStates if (node.usages().filter((n) -> !(n instanceof FrameState) || n.hasUsages()).isNotEmpty()) { throw new AssertionError("illegal constant node in AOT: " + node); } } } } } } super.checkNewNodes(b, plugin, newNodes); }
@Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { ResolvedJavaField field = b.getMetaAccess().lookupJavaField(STRING_VALUE_FIELD); b.addPush(JavaKind.Object, LoadFieldNode.create(b.getConstantFieldProvider(), b.getConstantReflection(), b.getMetaAccess(), b.getOptions(), b.getAssumptions(), value, field, false, false)); return true; } });
@Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { ResolvedJavaField field = b.getMetaAccess().lookupJavaField(STRING_VALUE_FIELD); b.addPush(JavaKind.Object, LoadFieldNode.create(b.getConstantFieldProvider(), b.getConstantReflection(), b.getMetaAccess(), b.getOptions(), b.getAssumptions(), value, field, false, false)); return true; } });
@Override public boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode[] args) { assert checkInjectedArgument(b, args[0], targetMethod); org.graalvm.compiler.options.OptionValues arg0 = b.getOptions(); boolean result = org.graalvm.compiler.hotspot.replacements.MonitorSnippets.doProfile(arg0); JavaConstant constant = JavaConstant.forInt(result ? 1 : 0); ConstantNode node = ConstantNode.forConstant(constant, b.getMetaAccess(), b.getGraph()); b.push(JavaKind.Int, node); b.notifyReplacedCall(targetMethod, node); return true; } @Override
@Override public boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode[] args) { assert checkInjectedArgument(b, args[0], targetMethod); org.graalvm.compiler.options.OptionValues arg0 = b.getOptions(); boolean result = org.graalvm.compiler.hotspot.replacements.MonitorSnippets.verifyBalancedMonitors(arg0); JavaConstant constant = JavaConstant.forInt(result ? 1 : 0); ConstantNode node = ConstantNode.forConstant(constant, b.getMetaAccess(), b.getGraph()); b.push(JavaKind.Int, node); b.notifyReplacedCall(targetMethod, node); return true; } @Override
private static boolean tryConstantFold(GraphBuilderContext b, ResolvedJavaField field, JavaConstant object) { ConstantNode result = ConstantFoldUtil.tryConstantFold(b.getConstantFieldProvider(), b.getConstantReflection(), b.getMetaAccess(), field, object, b.getOptions()); if (result != null) { result = b.getGraph().unique(result); b.push(field.getJavaKind(), result); return true; } return false; }
@Override public boolean handleLoadField(GraphBuilderContext b, ValueNode object, ResolvedJavaField field) { if (!ImmutableCode.getValue(b.getOptions()) || b.parsingIntrinsic()) { if (object.isConstant()) { JavaConstant asJavaConstant = object.asJavaConstant(); if (tryReadField(b, field, asJavaConstant)) { return true; } } } if (b.parsingIntrinsic() && wordOperationPlugin.handleLoadField(b, object, field)) { return true; } return false; }
@Override public void profileInvoke(GraphBuilderContext builder, ResolvedJavaMethod method, FrameState frameState) { assert shouldProfile(builder, method); OptionValues options = builder.getOptions(); if (Options.ProfileInvokes.getValue(options) && !method.isClassInitializer()) { ProfileNode p = builder.append(new ProfileInvokeNode(method, invokeNotifyFreqLog(options), invokeProfilePobabilityLog(options))); p.setStateBefore(frameState); } }
@Override public boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode[] args) { assert checkInjectedArgument(b, args[0], targetMethod); org.graalvm.compiler.options.OptionValues arg0 = b.getOptions(); boolean result = org.graalvm.compiler.hotspot.replacements.NewObjectSnippets.doProfile(arg0); JavaConstant constant = JavaConstant.forInt(result ? 1 : 0); ConstantNode node = ConstantNode.forConstant(constant, b.getMetaAccess(), b.getGraph()); b.push(JavaKind.Int, node); b.notifyReplacedCall(targetMethod, node); return true; } @Override
@Override public boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode[] args) { assert checkInjectedArgument(b, args[0], targetMethod); org.graalvm.compiler.options.OptionValues arg0 = b.getOptions(); boolean result = org.graalvm.compiler.hotspot.replacements.MonitorSnippets.useFastInflatedLocking(arg0); JavaConstant constant = JavaConstant.forInt(result ? 1 : 0); ConstantNode node = ConstantNode.forConstant(constant, b.getMetaAccess(), b.getGraph()); b.push(JavaKind.Int, node); b.notifyReplacedCall(targetMethod, node); return true; } @Override
@Override public boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode[] args) { assert checkInjectedArgument(b, args[0], targetMethod); org.graalvm.compiler.options.OptionValues arg0 = b.getOptions(); boolean result = org.graalvm.compiler.hotspot.stubs.UnwindExceptionToCallerStub.logging(arg0); JavaConstant constant = JavaConstant.forInt(result ? 1 : 0); ConstantNode node = ConstantNode.forConstant(constant, b.getMetaAccess(), b.getGraph()); b.push(JavaKind.Int, node); b.notifyReplacedCall(targetMethod, node); return true; } @Override
@Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { ResolvedJavaField field = b.getMetaAccess().lookupJavaField(STRING_CODER_FIELD); b.addPush(JavaKind.Int, LoadFieldNode.create(b.getConstantFieldProvider(), b.getConstantReflection(), b.getMetaAccess(), b.getOptions(), b.getAssumptions(), value, field, false, false)); return true; } });
@Override public boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode[] args) { assert checkInjectedArgument(b, args[0], targetMethod); org.graalvm.compiler.options.OptionValues arg0 = b.getOptions(); boolean result = org.graalvm.compiler.hotspot.replacements.NewObjectSnippets.withContext(arg0); JavaConstant constant = JavaConstant.forInt(result ? 1 : 0); ConstantNode node = ConstantNode.forConstant(constant, b.getMetaAccess(), b.getGraph()); b.push(JavaKind.Int, node); b.notifyReplacedCall(targetMethod, node); return true; } @Override
@Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode x, ValueNode y) { CanonicalizedCondition canonical = condition.canonicalize(); StructuredGraph graph = b.getGraph(); ValueNode lhs = canonical.mustMirror() ? y : x; ValueNode rhs = canonical.mustMirror() ? x : y; ValueNode trueValue = ConstantNode.forBoolean(!canonical.mustNegate(), graph); ValueNode falseValue = ConstantNode.forBoolean(canonical.mustNegate(), graph); LogicNode compare = CompareNode.createCompareNode(graph, b.getConstantReflection(), b.getMetaAccess(), b.getOptions(), null, canonical.getCanonicalCondition(), lhs, rhs, NodeView.DEFAULT); b.addPush(JavaKind.Boolean, new ConditionalNode(compare, trueValue, falseValue)); return true; } }
@Override public void profileIf(GraphBuilderContext builder, ResolvedJavaMethod method, int bci, LogicNode condition, int trueBranchBci, int falseBranchBci, FrameState frameState) { assert shouldProfile(builder, method); OptionValues options = builder.getOptions(); if (Options.ProfileBackedges.getValue(options) && (falseBranchBci <= bci || trueBranchBci <= bci)) { boolean negate = false; int targetBci = trueBranchBci; if (falseBranchBci <= bci) { assert trueBranchBci > bci; negate = true; targetBci = falseBranchBci; } else { assert trueBranchBci <= bci && falseBranchBci > bci; } ValueNode trueValue = builder.append(ConstantNode.forBoolean(!negate)); ValueNode falseValue = builder.append(ConstantNode.forBoolean(negate)); ConditionalNode branchCondition = builder.append(new ConditionalNode(condition, trueValue, falseValue)); ProfileNode p = builder.append(new ProfileBranchNode(method, backedgeNotifyFreqLog(options), backedgeProfilePobabilityLog(options), branchCondition, bci, targetBci)); p.setStateBefore(frameState); } } }
@Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode object, ValueNode offset, ValueNode condition, ValueNode location) { if (location.isConstant()) { LocationIdentity locationIdentity; if (location.isNullConstant()) { locationIdentity = LocationIdentity.any(); } else { locationIdentity = ObjectLocationIdentity.create(location.asJavaConstant()); } LogicNode compare = b.addWithInputs(CompareNode.createCompareNode(b.getConstantReflection(), b.getMetaAccess(), b.getOptions(), null, CanonicalCondition.EQ, condition, ConstantNode.forBoolean(true, object.graph()), NodeView.DEFAULT)); ConditionAnchorNode anchor = b.add(new ConditionAnchorNode(compare)); b.addPush(returnKind, b.add(new GuardedUnsafeLoadNode(b.addNonNullCast(object), offset, returnKind, locationIdentity, anchor))); return true; } else if (canDelayIntrinsification) { return false; } else { RawLoadNode load = b.addPush(returnKind, new RawLoadNode(object, offset, returnKind, LocationIdentity.any(), true)); logPerformanceWarningLocationNotConstant(location, targetMethod, load); return true; } } }