< prev index next >

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

Print this page




  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 
  25 package org.graalvm.compiler.replacements;
  26 
  27 import static jdk.vm.ci.code.MemoryBarriers.JMM_POST_VOLATILE_READ;
  28 import static jdk.vm.ci.code.MemoryBarriers.JMM_POST_VOLATILE_WRITE;
  29 import static jdk.vm.ci.code.MemoryBarriers.JMM_PRE_VOLATILE_READ;
  30 import static jdk.vm.ci.code.MemoryBarriers.JMM_PRE_VOLATILE_WRITE;
  31 import static jdk.vm.ci.code.MemoryBarriers.LOAD_LOAD;
  32 import static jdk.vm.ci.code.MemoryBarriers.LOAD_STORE;
  33 import static jdk.vm.ci.code.MemoryBarriers.STORE_LOAD;
  34 import static jdk.vm.ci.code.MemoryBarriers.STORE_STORE;
  35 import static org.graalvm.compiler.nodes.NamedLocationIdentity.OFF_HEAP_LOCATION;
  36 import static org.graalvm.compiler.serviceprovider.GraalServices.Java11OrEarlier;
  37 import static org.graalvm.compiler.serviceprovider.GraalServices.Java8OrEarlier;
  38 
  39 import java.lang.reflect.Array;
  40 import java.lang.reflect.Field;
  41 import java.util.Arrays;
  42 
  43 import org.graalvm.compiler.api.directives.GraalDirectives;
  44 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
  45 import org.graalvm.compiler.bytecode.BytecodeProvider;
  46 import org.graalvm.compiler.core.common.calc.Condition;
  47 import org.graalvm.compiler.core.common.calc.Condition.CanonicalizedCondition;
  48 import org.graalvm.compiler.core.common.calc.UnsignedMath;
  49 import org.graalvm.compiler.core.common.type.ObjectStamp;
  50 import org.graalvm.compiler.core.common.type.Stamp;
  51 import org.graalvm.compiler.core.common.type.StampFactory;
  52 import org.graalvm.compiler.core.common.type.TypeReference;
  53 import org.graalvm.compiler.debug.GraalError;
  54 import org.graalvm.compiler.graph.Edges;
  55 import org.graalvm.compiler.graph.Node;
  56 import org.graalvm.compiler.graph.NodeList;
  57 import org.graalvm.compiler.java.IntegerExactOpSpeculation;
  58 import org.graalvm.compiler.java.IntegerExactOpSpeculation.IntegerExactOp;
  59 import org.graalvm.compiler.nodes.AbstractBeginNode;
  60 import org.graalvm.compiler.nodes.BeginNode;
  61 import org.graalvm.compiler.nodes.ConstantNode;
  62 import org.graalvm.compiler.nodes.DeoptimizeNode;
  63 import org.graalvm.compiler.nodes.EndNode;
  64 import org.graalvm.compiler.nodes.FixedGuardNode;
  65 import org.graalvm.compiler.nodes.FixedWithNextNode;
  66 import org.graalvm.compiler.nodes.IfNode;
  67 import org.graalvm.compiler.nodes.LogicNode;
  68 import org.graalvm.compiler.nodes.MergeNode;

  69 import org.graalvm.compiler.nodes.NodeView;
  70 import org.graalvm.compiler.nodes.StateSplit;
  71 import org.graalvm.compiler.nodes.StructuredGraph;
  72 import org.graalvm.compiler.nodes.ValueNode;
  73 import org.graalvm.compiler.nodes.ValuePhiNode;
  74 import org.graalvm.compiler.nodes.calc.AbsNode;
  75 import org.graalvm.compiler.nodes.calc.CompareNode;
  76 import org.graalvm.compiler.nodes.calc.ConditionalNode;
  77 import org.graalvm.compiler.nodes.calc.FloatEqualsNode;
  78 import org.graalvm.compiler.nodes.calc.IntegerEqualsNode;
  79 import org.graalvm.compiler.nodes.calc.IsNullNode;
  80 import org.graalvm.compiler.nodes.calc.NarrowNode;
  81 import org.graalvm.compiler.nodes.calc.ReinterpretNode;
  82 import org.graalvm.compiler.nodes.calc.RightShiftNode;
  83 import org.graalvm.compiler.nodes.calc.SignExtendNode;
  84 import org.graalvm.compiler.nodes.calc.SqrtNode;
  85 import org.graalvm.compiler.nodes.calc.UnsignedDivNode;
  86 import org.graalvm.compiler.nodes.calc.UnsignedRemNode;
  87 import org.graalvm.compiler.nodes.calc.ZeroExtendNode;
  88 import org.graalvm.compiler.nodes.debug.BindToRegisterNode;
  89 import org.graalvm.compiler.nodes.debug.BlackholeNode;
  90 import org.graalvm.compiler.nodes.debug.ControlFlowAnchorNode;
  91 import org.graalvm.compiler.nodes.debug.SpillRegistersNode;
  92 import org.graalvm.compiler.nodes.extended.BoxNode;
  93 import org.graalvm.compiler.nodes.extended.BranchProbabilityNode;
  94 import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode.BytecodeExceptionKind;
  95 import org.graalvm.compiler.nodes.extended.GetClassNode;



  96 import org.graalvm.compiler.nodes.extended.MembarNode;
  97 import org.graalvm.compiler.nodes.extended.OpaqueNode;
  98 import org.graalvm.compiler.nodes.extended.RawLoadNode;
  99 import org.graalvm.compiler.nodes.extended.RawStoreNode;
 100 import org.graalvm.compiler.nodes.extended.UnboxNode;
 101 import org.graalvm.compiler.nodes.extended.UnsafeMemoryLoadNode;
 102 import org.graalvm.compiler.nodes.extended.UnsafeMemoryStoreNode;
 103 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
 104 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
 105 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.Receiver;
 106 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
 107 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration;
 108 import org.graalvm.compiler.nodes.java.ClassIsAssignableFromNode;
 109 import org.graalvm.compiler.nodes.java.DynamicNewArrayNode;
 110 import org.graalvm.compiler.nodes.java.DynamicNewInstanceNode;
 111 import org.graalvm.compiler.nodes.java.InstanceOfDynamicNode;
 112 import org.graalvm.compiler.nodes.java.LoadFieldNode;
 113 import org.graalvm.compiler.nodes.java.RegisterFinalizerNode;
 114 import org.graalvm.compiler.nodes.java.UnsafeCompareAndExchangeNode;
 115 import org.graalvm.compiler.nodes.java.UnsafeCompareAndSwapNode;


 116 import org.graalvm.compiler.nodes.type.StampTool;
 117 import org.graalvm.compiler.nodes.util.GraphUtil;
 118 import org.graalvm.compiler.nodes.virtual.EnsureVirtualizedNode;
 119 import org.graalvm.compiler.replacements.nodes.ProfileBooleanNode;
 120 import org.graalvm.compiler.replacements.nodes.ReverseBytesNode;
 121 import org.graalvm.compiler.replacements.nodes.VirtualizableInvokeMacroNode;
 122 import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerAddExactNode;

 123 import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerAddExactSplitNode;
 124 import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerExactArithmeticNode;
 125 import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerExactArithmeticSplitNode;
 126 import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerMulExactNode;

 127 import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerMulExactSplitNode;
 128 import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerSubExactNode;

 129 import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerSubExactSplitNode;

 130 import jdk.internal.vm.compiler.word.LocationIdentity;
 131 
 132 import jdk.vm.ci.code.BytecodePosition;
 133 import jdk.vm.ci.meta.DeoptimizationAction;
 134 import jdk.vm.ci.meta.DeoptimizationReason;
 135 import jdk.vm.ci.meta.JavaConstant;
 136 import jdk.vm.ci.meta.JavaKind;
 137 import jdk.vm.ci.meta.MetaAccessProvider;
 138 import jdk.vm.ci.meta.ResolvedJavaField;
 139 import jdk.vm.ci.meta.ResolvedJavaMethod;
 140 import jdk.vm.ci.meta.ResolvedJavaType;
 141 import jdk.vm.ci.meta.SpeculationLog;
 142 import jdk.vm.ci.meta.SpeculationLog.Speculation;
 143 import jdk.vm.ci.meta.SpeculationLog.SpeculationReason;
 144 import sun.misc.Unsafe;
 145 
 146 /**
 147  * Provides non-runtime specific {@link InvocationPlugin}s.
 148  */
 149 public class StandardGraphBuilderPlugins {


 180     static {
 181         Field coder = null;
 182         try {
 183             STRING_VALUE_FIELD = String.class.getDeclaredField("value");
 184             if (!Java8OrEarlier) {
 185                 coder = String.class.getDeclaredField("coder");
 186             }
 187         } catch (NoSuchFieldException e) {
 188             throw new GraalError(e);
 189         }
 190         STRING_CODER_FIELD = coder;
 191     }
 192 
 193     private static void registerStringPlugins(InvocationPlugins plugins, BytecodeProvider bytecodeProvider, SnippetReflectionProvider snippetReflection) {
 194         final Registration r = new Registration(plugins, String.class, bytecodeProvider);
 195         r.register1("hashCode", Receiver.class, new InvocationPlugin() {
 196             @Override
 197             public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
 198                 if (receiver.isConstant()) {
 199                     String s = snippetReflection.asObject(String.class, (JavaConstant) receiver.get().asConstant());
 200                     b.addPush(JavaKind.Int, b.add(ConstantNode.forInt(s.hashCode())));
 201                     return true;


 202                 }
 203                 return false;
 204             }
 205         });
 206 
 207         if (Java8OrEarlier) {
 208             r.registerMethodSubstitution(StringSubstitutions.class, "equals", Receiver.class, Object.class);
 209 
 210             r.register7("indexOf", char[].class, int.class, int.class, char[].class, int.class, int.class, int.class, new StringIndexOfConstantPlugin());
 211 
 212             Registration sr = new Registration(plugins, StringSubstitutions.class);
 213             sr.register1("getValue", String.class, new InvocationPlugin() {
 214                 @Override
 215                 public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) {
 216                     ResolvedJavaField field = b.getMetaAccess().lookupJavaField(STRING_VALUE_FIELD);
 217                     b.addPush(JavaKind.Object, LoadFieldNode.create(b.getConstantFieldProvider(), b.getConstantReflection(), b.getMetaAccess(),
 218                                     b.getOptions(), b.getAssumptions(), value, field, false, false));
 219                     return true;
 220                 }
 221             });
 222         } else {
 223             r.registerMethodSubstitution(JDK9StringSubstitutions.class, "equals", Receiver.class, Object.class);

















 224 
 225             final Registration latin1r = new Registration(plugins, "java.lang.StringLatin1", bytecodeProvider);
 226             latin1r.register5("indexOf", byte[].class, int.class, byte[].class, int.class, int.class, new StringLatin1IndexOfConstantPlugin());
 227 
 228             final Registration utf16r = new Registration(plugins, "java.lang.StringUTF16", bytecodeProvider);
 229             utf16r.register5("indexOfUnsafe", byte[].class, int.class, byte[].class, int.class, int.class, new StringUTF16IndexOfConstantPlugin());



 230 
 231             Registration sr = new Registration(plugins, JDK9StringSubstitutions.class);
 232             sr.register1("getValue", String.class, new InvocationPlugin() {
 233                 @Override
 234                 public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) {
 235                     ResolvedJavaField field = b.getMetaAccess().lookupJavaField(STRING_VALUE_FIELD);
 236                     b.addPush(JavaKind.Object, LoadFieldNode.create(b.getConstantFieldProvider(), b.getConstantReflection(), b.getMetaAccess(),
 237                                     b.getOptions(), b.getAssumptions(), value, field, false, false));
 238                     return true;
 239                 }
 240             });
 241             sr.register1("getCoder", String.class, new InvocationPlugin() {
 242                 @Override
 243                 public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) {
 244                     ResolvedJavaField field = b.getMetaAccess().lookupJavaField(STRING_CODER_FIELD);
 245                     b.addPush(JavaKind.Int, LoadFieldNode.create(b.getConstantFieldProvider(), b.getConstantReflection(), b.getMetaAccess(),
 246                                     b.getOptions(), b.getAssumptions(), value, field, false, false));
 247                     return true;
 248                 }
 249             });


 512         });
 513         r.register1("doubleToLongBits", double.class, new InvocationPlugin() {
 514             @Override
 515             public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) {
 516                 LogicNode notNan = b.append(FloatEqualsNode.create(value, value, NodeView.DEFAULT));
 517                 ValueNode raw = b.append(ReinterpretNode.create(JavaKind.Long, value, NodeView.DEFAULT));
 518                 ValueNode result = b.append(ConditionalNode.create(notNan, raw, ConstantNode.forLong(0x7ff8000000000000L), NodeView.DEFAULT));
 519                 b.push(JavaKind.Long, result);
 520                 return true;
 521             }
 522         });
 523         r.register1("longBitsToDouble", long.class, new InvocationPlugin() {
 524             @Override
 525             public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) {
 526                 b.push(JavaKind.Double, b.append(ReinterpretNode.create(JavaKind.Double, value, NodeView.DEFAULT)));
 527                 return true;
 528             }
 529         });
 530     }
 531 
 532     private static ValueNode createIntegerExactArithmeticNode(ValueNode x, ValueNode y, SpeculationReason speculation, IntegerExactOp op) {































 533         switch (op) {
 534             case INTEGER_ADD_EXACT:
 535             case INTEGER_INCREMENT_EXACT:
 536                 return new IntegerAddExactNode(x, y, speculation);
 537             case INTEGER_SUBTRACT_EXACT:
 538             case INTEGER_DECREMENT_EXACT:
 539                 return new IntegerSubExactNode(x, y, speculation);
 540             case INTEGER_MULTIPLY_EXACT:
 541                 return new IntegerMulExactNode(x, y, speculation);
 542             default:
 543                 throw GraalError.shouldNotReachHere("Unknown integer exact operation.");
 544         }
 545     }
 546 
 547     private static IntegerExactArithmeticSplitNode createIntegerExactSplit(ValueNode x, ValueNode y, AbstractBeginNode exceptionEdge, IntegerExactOp op) {
 548         switch (op) {
 549             case INTEGER_ADD_EXACT:
 550             case INTEGER_INCREMENT_EXACT:
 551                 return new IntegerAddExactSplitNode(x.stamp(NodeView.DEFAULT).unrestricted(), x, y, null, exceptionEdge);
 552             case INTEGER_SUBTRACT_EXACT:
 553             case INTEGER_DECREMENT_EXACT:
 554                 return new IntegerSubExactSplitNode(x.stamp(NodeView.DEFAULT).unrestricted(), x, y, null, exceptionEdge);
 555             case INTEGER_MULTIPLY_EXACT:
 556                 return new IntegerMulExactSplitNode(x.stamp(NodeView.DEFAULT).unrestricted(), x, y, null, exceptionEdge);
 557             default:
 558                 throw GraalError.shouldNotReachHere("Unknown integer exact operation.");
 559         }
 560     }
 561 
 562     private static boolean createIntegerExactOperation(GraphBuilderContext b, JavaKind kind, ValueNode x, ValueNode y, IntegerExactOp op) {
 563         BytecodeExceptionKind exceptionKind = kind == JavaKind.Int ? BytecodeExceptionKind.INTEGER_EXACT_OVERFLOW : BytecodeExceptionKind.LONG_EXACT_OVERFLOW;
 564         AbstractBeginNode exceptionEdge = b.genExplicitExceptionEdge(exceptionKind);
 565         if (exceptionEdge != null) {
 566             IntegerExactArithmeticSplitNode split = b.addPush(kind, createIntegerExactSplit(x, y, exceptionEdge, op));
 567             split.setNext(b.add(new BeginNode()));
 568             return true;

 569         }
 570         return false;
 571     }
 572 
 573     private static void registerMathPlugins(InvocationPlugins plugins, boolean allowDeoptimization) {
 574         Registration r = new Registration(plugins, Math.class);
 575         if (allowDeoptimization) {
 576             for (JavaKind kind : new JavaKind[]{JavaKind.Int, JavaKind.Long}) {
 577                 Class<?> type = kind.toJavaClass();
 578 
 579                 r.register1("decrementExact", type, new InvocationPlugin() {
 580                     @Override
 581                     public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode x) {
 582                         ConstantNode y = b.add(ConstantNode.forIntegerKind(kind, 1));
 583                         return createIntegerExactOperation(b, kind, x, y, IntegerExactOp.INTEGER_DECREMENT_EXACT);

 584                     }
 585                 });
 586 
 587                 r.register1("incrementExact", type, new InvocationPlugin() {
 588                     @Override
 589                     public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode x) {
 590                         ConstantNode y = b.add(ConstantNode.forIntegerKind(kind, 1));
 591                         return createIntegerExactOperation(b, kind, x, y, IntegerExactOp.INTEGER_INCREMENT_EXACT);

 592                     }
 593                 });
 594 
 595                 r.register2("addExact", type, type, new InvocationPlugin() {
 596                     @Override
 597                     public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode x, ValueNode y) {
 598                         return createIntegerExactOperation(b, kind, x, y, IntegerExactOp.INTEGER_ADD_EXACT);

 599                     }
 600                 });
 601 
 602                 r.register2("subtractExact", type, type, new InvocationPlugin() {
 603                     @Override
 604                     public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode x, ValueNode y) {
 605                         return createIntegerExactOperation(b, kind, x, y, IntegerExactOp.INTEGER_SUBTRACT_EXACT);

 606                     }
 607                 });
 608 
 609                 r.register2("multiplyExact", type, type, new InvocationPlugin() {
 610                     @Override
 611                     public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode x, ValueNode y) {
 612                         return createIntegerExactOperation(b, kind, x, y, IntegerExactOp.INTEGER_MULTIPLY_EXACT);
 613                      }

 614                 });
 615             }
 616         }
 617         r.register1("abs", Float.TYPE, new InvocationPlugin() {
 618 
 619             @Override
 620             public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) {
 621                 b.push(JavaKind.Float, b.append(new AbsNode(value).canonical(null)));
 622                 return true;
 623             }
 624         });
 625         r.register1("abs", Double.TYPE, new InvocationPlugin() {
 626             @Override
 627             public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) {
 628                 b.push(JavaKind.Double, b.append(new AbsNode(value).canonical(null)));
 629                 return true;
 630             }
 631         });
 632         r.register1("sqrt", Double.TYPE, new MathSqrtPlugin());
 633     }


1083         }
1084     }
1085 
1086     public static class UnsafeFencePlugin implements InvocationPlugin {
1087 
1088         private final int barriers;
1089 
1090         public UnsafeFencePlugin(int barriers) {
1091             this.barriers = barriers;
1092         }
1093 
1094         @Override
1095         public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver unsafe) {
1096             // Emits a null-check for the otherwise unused receiver
1097             unsafe.get();
1098             b.add(new MembarNode(barriers));
1099             return true;
1100         }
1101     }
1102 
1103     private static final class DirectiveSpeculationReason implements SpeculationLog.SpeculationReason {
1104         private final BytecodePosition pos;
1105 
1106         private DirectiveSpeculationReason(BytecodePosition pos) {
1107             this.pos = pos;
1108         }
1109 
1110         @Override
1111         public int hashCode() {
1112             return pos.hashCode();
1113         }
1114 
1115         @Override
1116         public boolean equals(Object obj) {
1117             return obj instanceof DirectiveSpeculationReason && ((DirectiveSpeculationReason) obj).pos.equals(this.pos);
1118         }
1119     }
1120 
1121     private static void registerGraalDirectivesPlugins(InvocationPlugins plugins) {
1122         Registration r = new Registration(plugins, GraalDirectives.class);
1123         r.register0("deoptimize", new InvocationPlugin() {
1124             @Override
1125             public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
1126                 b.add(new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.TransferToInterpreter));
1127                 return true;
1128             }
1129         });
1130 
1131         r.register0("deoptimizeAndInvalidate", new InvocationPlugin() {
1132             @Override
1133             public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
1134                 b.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TransferToInterpreter));
1135                 return true;
1136             }
1137         });
1138 
1139         r.register0("deoptimizeAndInvalidateWithSpeculation", new InvocationPlugin() {
1140             @Override
1141             public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
1142                 GraalError.guarantee(b.getGraph().getSpeculationLog() != null, "A speculation log is need to use `deoptimizeAndInvalidateWithSpeculation`");
1143                 BytecodePosition pos = new BytecodePosition(null, b.getMethod(), b.bci());
1144                 DirectiveSpeculationReason reason = new DirectiveSpeculationReason(pos);
1145                 Speculation speculation;
1146                 if (b.getGraph().getSpeculationLog().maySpeculate(reason)) {
1147                     speculation = b.getGraph().getSpeculationLog().speculate(reason);
1148                 } else {
1149                     speculation = SpeculationLog.NO_SPECULATION;
1150                 }
1151                 b.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TransferToInterpreter, speculation));
1152                 return true;
1153             }
1154         });
1155 
1156         r.register0("inCompiledCode", new InvocationPlugin() {
1157             @Override
1158             public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
1159                 b.addPush(JavaKind.Boolean, ConstantNode.forBoolean(true));
1160                 return true;
1161             }
1162         });
1163 
1164         r.register0("controlFlowAnchor", new InvocationPlugin() {


1307             }
1308 
1309             @Override
1310             public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode result, ValueNode counters) {
1311                 if (result.isConstant()) {
1312                     b.push(JavaKind.Boolean, result);
1313                     return true;
1314                 }
1315                 if (counters.isConstant()) {
1316                     ValueNode newResult = result;
1317                     int[] ctrs = snippetReflection.asObject(int[].class, (JavaConstant) counters.asConstant());
1318                     if (ctrs != null && ctrs.length == 2) {
1319                         int falseCount = ctrs[0];
1320                         int trueCount = ctrs[1];
1321                         int totalCount = trueCount + falseCount;
1322 
1323                         if (totalCount == 0) {
1324                             b.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TransferToInterpreter));
1325                         } else if (falseCount == 0 || trueCount == 0) {
1326                             boolean expected = falseCount == 0;
1327                             LogicNode condition = b.addWithInputs(
1328                                             IntegerEqualsNode.create(b.getConstantReflection(), b.getMetaAccess(), b.getOptions(), null, result, b.add(ConstantNode.forBoolean(!expected)),
1329                                                             NodeView.DEFAULT));
1330                             b.append(new FixedGuardNode(condition, DeoptimizationReason.UnreachedCode, DeoptimizationAction.InvalidateReprofile, true));
1331                             newResult = b.add(ConstantNode.forBoolean(expected));
1332                         } else {
1333                             // We cannot use BranchProbabilityNode here since there's no guarantee
1334                             // the result of MethodHandleImpl.profileBoolean() is used as the
1335                             // test in an `if` statement (as required by BranchProbabilityNode).
1336                         }
1337                     }
1338                     b.addPush(JavaKind.Boolean, newResult);
1339                     return true;
1340                 }
1341                 b.addPush(JavaKind.Boolean,
1342                                 new ProfileBooleanNode(snippetReflection, b.getInvokeKind(), targetMethod, b.bci(), b.getInvokeReturnStamp(b.getAssumptions()), result, counters));
1343                 return true;
1344             }
1345         });
1346     }
1347 


  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 
  25 package org.graalvm.compiler.replacements;
  26 
  27 import static jdk.vm.ci.code.MemoryBarriers.JMM_POST_VOLATILE_READ;
  28 import static jdk.vm.ci.code.MemoryBarriers.JMM_POST_VOLATILE_WRITE;
  29 import static jdk.vm.ci.code.MemoryBarriers.JMM_PRE_VOLATILE_READ;
  30 import static jdk.vm.ci.code.MemoryBarriers.JMM_PRE_VOLATILE_WRITE;
  31 import static jdk.vm.ci.code.MemoryBarriers.LOAD_LOAD;
  32 import static jdk.vm.ci.code.MemoryBarriers.LOAD_STORE;
  33 import static jdk.vm.ci.code.MemoryBarriers.STORE_LOAD;
  34 import static jdk.vm.ci.code.MemoryBarriers.STORE_STORE;
  35 import static org.graalvm.compiler.nodes.NamedLocationIdentity.OFF_HEAP_LOCATION;
  36 import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.Java11OrEarlier;
  37 import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.Java8OrEarlier;
  38 
  39 import java.lang.reflect.Array;
  40 import java.lang.reflect.Field;
  41 import java.util.Arrays;
  42 
  43 import org.graalvm.compiler.api.directives.GraalDirectives;
  44 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
  45 import org.graalvm.compiler.bytecode.BytecodeProvider;
  46 import org.graalvm.compiler.core.common.calc.Condition;
  47 import org.graalvm.compiler.core.common.calc.Condition.CanonicalizedCondition;
  48 import org.graalvm.compiler.core.common.calc.UnsignedMath;
  49 import org.graalvm.compiler.core.common.type.ObjectStamp;
  50 import org.graalvm.compiler.core.common.type.Stamp;
  51 import org.graalvm.compiler.core.common.type.StampFactory;
  52 import org.graalvm.compiler.core.common.type.TypeReference;
  53 import org.graalvm.compiler.debug.GraalError;
  54 import org.graalvm.compiler.graph.Edges;
  55 import org.graalvm.compiler.graph.Node;
  56 import org.graalvm.compiler.graph.NodeList;


  57 import org.graalvm.compiler.nodes.AbstractBeginNode;
  58 import org.graalvm.compiler.nodes.BeginNode;
  59 import org.graalvm.compiler.nodes.ConstantNode;
  60 import org.graalvm.compiler.nodes.DeoptimizeNode;
  61 import org.graalvm.compiler.nodes.EndNode;
  62 import org.graalvm.compiler.nodes.FixedGuardNode;
  63 import org.graalvm.compiler.nodes.FixedWithNextNode;
  64 import org.graalvm.compiler.nodes.IfNode;
  65 import org.graalvm.compiler.nodes.LogicNode;
  66 import org.graalvm.compiler.nodes.MergeNode;
  67 import org.graalvm.compiler.nodes.NamedLocationIdentity;
  68 import org.graalvm.compiler.nodes.NodeView;
  69 import org.graalvm.compiler.nodes.StateSplit;
  70 import org.graalvm.compiler.nodes.StructuredGraph;
  71 import org.graalvm.compiler.nodes.ValueNode;
  72 import org.graalvm.compiler.nodes.ValuePhiNode;
  73 import org.graalvm.compiler.nodes.calc.AbsNode;
  74 import org.graalvm.compiler.nodes.calc.CompareNode;
  75 import org.graalvm.compiler.nodes.calc.ConditionalNode;
  76 import org.graalvm.compiler.nodes.calc.FloatEqualsNode;
  77 import org.graalvm.compiler.nodes.calc.IntegerEqualsNode;
  78 import org.graalvm.compiler.nodes.calc.IsNullNode;
  79 import org.graalvm.compiler.nodes.calc.NarrowNode;
  80 import org.graalvm.compiler.nodes.calc.ReinterpretNode;
  81 import org.graalvm.compiler.nodes.calc.RightShiftNode;
  82 import org.graalvm.compiler.nodes.calc.SignExtendNode;
  83 import org.graalvm.compiler.nodes.calc.SqrtNode;
  84 import org.graalvm.compiler.nodes.calc.UnsignedDivNode;
  85 import org.graalvm.compiler.nodes.calc.UnsignedRemNode;
  86 import org.graalvm.compiler.nodes.calc.ZeroExtendNode;
  87 import org.graalvm.compiler.nodes.debug.BindToRegisterNode;
  88 import org.graalvm.compiler.nodes.debug.BlackholeNode;
  89 import org.graalvm.compiler.nodes.debug.ControlFlowAnchorNode;
  90 import org.graalvm.compiler.nodes.debug.SpillRegistersNode;
  91 import org.graalvm.compiler.nodes.extended.BoxNode;
  92 import org.graalvm.compiler.nodes.extended.BranchProbabilityNode;
  93 import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode.BytecodeExceptionKind;
  94 import org.graalvm.compiler.nodes.extended.GetClassNode;
  95 import org.graalvm.compiler.nodes.extended.GuardingNode;
  96 import org.graalvm.compiler.nodes.extended.JavaReadNode;
  97 import org.graalvm.compiler.nodes.extended.JavaWriteNode;
  98 import org.graalvm.compiler.nodes.extended.MembarNode;
  99 import org.graalvm.compiler.nodes.extended.OpaqueNode;
 100 import org.graalvm.compiler.nodes.extended.RawLoadNode;
 101 import org.graalvm.compiler.nodes.extended.RawStoreNode;
 102 import org.graalvm.compiler.nodes.extended.UnboxNode;
 103 import org.graalvm.compiler.nodes.extended.UnsafeMemoryLoadNode;
 104 import org.graalvm.compiler.nodes.extended.UnsafeMemoryStoreNode;
 105 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
 106 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
 107 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.Receiver;
 108 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
 109 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration;
 110 import org.graalvm.compiler.nodes.java.ClassIsAssignableFromNode;
 111 import org.graalvm.compiler.nodes.java.DynamicNewArrayNode;
 112 import org.graalvm.compiler.nodes.java.DynamicNewInstanceNode;
 113 import org.graalvm.compiler.nodes.java.InstanceOfDynamicNode;
 114 import org.graalvm.compiler.nodes.java.LoadFieldNode;
 115 import org.graalvm.compiler.nodes.java.RegisterFinalizerNode;
 116 import org.graalvm.compiler.nodes.java.UnsafeCompareAndExchangeNode;
 117 import org.graalvm.compiler.nodes.java.UnsafeCompareAndSwapNode;
 118 import org.graalvm.compiler.nodes.memory.HeapAccess;
 119 import org.graalvm.compiler.nodes.memory.address.IndexAddressNode;
 120 import org.graalvm.compiler.nodes.type.StampTool;
 121 import org.graalvm.compiler.nodes.util.GraphUtil;
 122 import org.graalvm.compiler.nodes.virtual.EnsureVirtualizedNode;
 123 import org.graalvm.compiler.replacements.nodes.ProfileBooleanNode;
 124 import org.graalvm.compiler.replacements.nodes.ReverseBytesNode;
 125 import org.graalvm.compiler.replacements.nodes.VirtualizableInvokeMacroNode;
 126 import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerAddExactNode;
 127 import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerAddExactOverflowNode;
 128 import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerAddExactSplitNode;

 129 import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerExactArithmeticSplitNode;
 130 import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerMulExactNode;
 131 import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerMulExactOverflowNode;
 132 import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerMulExactSplitNode;
 133 import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerSubExactNode;
 134 import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerSubExactOverflowNode;
 135 import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerSubExactSplitNode;
 136 import org.graalvm.compiler.serviceprovider.SpeculationReasonGroup;
 137 import jdk.internal.vm.compiler.word.LocationIdentity;
 138 
 139 import jdk.vm.ci.code.BytecodePosition;
 140 import jdk.vm.ci.meta.DeoptimizationAction;
 141 import jdk.vm.ci.meta.DeoptimizationReason;
 142 import jdk.vm.ci.meta.JavaConstant;
 143 import jdk.vm.ci.meta.JavaKind;
 144 import jdk.vm.ci.meta.MetaAccessProvider;
 145 import jdk.vm.ci.meta.ResolvedJavaField;
 146 import jdk.vm.ci.meta.ResolvedJavaMethod;
 147 import jdk.vm.ci.meta.ResolvedJavaType;
 148 import jdk.vm.ci.meta.SpeculationLog;
 149 import jdk.vm.ci.meta.SpeculationLog.Speculation;
 150 import jdk.vm.ci.meta.SpeculationLog.SpeculationReason;
 151 import sun.misc.Unsafe;
 152 
 153 /**
 154  * Provides non-runtime specific {@link InvocationPlugin}s.
 155  */
 156 public class StandardGraphBuilderPlugins {


 187     static {
 188         Field coder = null;
 189         try {
 190             STRING_VALUE_FIELD = String.class.getDeclaredField("value");
 191             if (!Java8OrEarlier) {
 192                 coder = String.class.getDeclaredField("coder");
 193             }
 194         } catch (NoSuchFieldException e) {
 195             throw new GraalError(e);
 196         }
 197         STRING_CODER_FIELD = coder;
 198     }
 199 
 200     private static void registerStringPlugins(InvocationPlugins plugins, BytecodeProvider bytecodeProvider, SnippetReflectionProvider snippetReflection) {
 201         final Registration r = new Registration(plugins, String.class, bytecodeProvider);
 202         r.register1("hashCode", Receiver.class, new InvocationPlugin() {
 203             @Override
 204             public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
 205                 if (receiver.isConstant()) {
 206                     String s = snippetReflection.asObject(String.class, (JavaConstant) receiver.get().asConstant());
 207                     if (s != null) {
 208                         b.addPush(JavaKind.Int, b.add(ConstantNode.forInt(s.hashCode())));
 209                         return true;
 210                     }
 211                 }
 212                 return false;
 213             }
 214         });
 215 
 216         if (Java8OrEarlier) {
 217             r.registerMethodSubstitution(StringSubstitutions.class, "equals", Receiver.class, Object.class);
 218 
 219             r.register7("indexOf", char[].class, int.class, int.class, char[].class, int.class, int.class, int.class, new StringIndexOfConstantPlugin());
 220 
 221             Registration sr = new Registration(plugins, StringSubstitutions.class);
 222             sr.register1("getValue", String.class, new InvocationPlugin() {
 223                 @Override
 224                 public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) {
 225                     ResolvedJavaField field = b.getMetaAccess().lookupJavaField(STRING_VALUE_FIELD);
 226                     b.addPush(JavaKind.Object, LoadFieldNode.create(b.getConstantFieldProvider(), b.getConstantReflection(), b.getMetaAccess(),
 227                                     b.getOptions(), b.getAssumptions(), value, field, false, false));
 228                     return true;
 229                 }
 230             });
 231         } else {
 232             r.registerMethodSubstitution(JDK9StringSubstitutions.class, "equals", Receiver.class, Object.class);
 233             Registration utf16sub = new Registration(plugins, StringUTF16Substitutions.class, bytecodeProvider);
 234             utf16sub.register2("getCharDirect", byte[].class, int.class, new InvocationPlugin() {
 235                 @Override
 236                 public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg1, ValueNode arg2) {
 237                     b.addPush(JavaKind.Char, new JavaReadNode(JavaKind.Char, new IndexAddressNode(arg1, arg2, JavaKind.Byte), NamedLocationIdentity.getArrayLocation(JavaKind.Byte),
 238                                     HeapAccess.BarrierType.NONE, false));
 239                     return true;
 240                 }
 241             });
 242             utf16sub.register3("putCharDirect", byte[].class, int.class, int.class, new InvocationPlugin() {
 243                 @Override
 244                 public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg1, ValueNode arg2, ValueNode arg3) {
 245                     b.add(new JavaWriteNode(JavaKind.Char, new IndexAddressNode(arg1, arg2, JavaKind.Byte), NamedLocationIdentity.getArrayLocation(JavaKind.Byte), arg3,
 246                                     HeapAccess.BarrierType.NONE, false));
 247                     return true;
 248                 }
 249             });
 250 
 251             final Registration latin1r = new Registration(plugins, "java.lang.StringLatin1", bytecodeProvider);
 252             latin1r.register5("indexOf", byte[].class, int.class, byte[].class, int.class, int.class, new StringLatin1IndexOfConstantPlugin());
 253 
 254             final Registration utf16r = new Registration(plugins, "java.lang.StringUTF16", bytecodeProvider);
 255             utf16r.register5("indexOfUnsafe", byte[].class, int.class, byte[].class, int.class, int.class, new StringUTF16IndexOfConstantPlugin());
 256             utf16r.setAllowOverwrite(true);
 257             utf16r.registerMethodSubstitution(StringUTF16Substitutions.class, "getChar", byte[].class, int.class);
 258             utf16r.registerMethodSubstitution(StringUTF16Substitutions.class, "putChar", byte[].class, int.class, int.class);
 259 
 260             Registration sr = new Registration(plugins, JDK9StringSubstitutions.class);
 261             sr.register1("getValue", String.class, new InvocationPlugin() {
 262                 @Override
 263                 public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) {
 264                     ResolvedJavaField field = b.getMetaAccess().lookupJavaField(STRING_VALUE_FIELD);
 265                     b.addPush(JavaKind.Object, LoadFieldNode.create(b.getConstantFieldProvider(), b.getConstantReflection(), b.getMetaAccess(),
 266                                     b.getOptions(), b.getAssumptions(), value, field, false, false));
 267                     return true;
 268                 }
 269             });
 270             sr.register1("getCoder", String.class, new InvocationPlugin() {
 271                 @Override
 272                 public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) {
 273                     ResolvedJavaField field = b.getMetaAccess().lookupJavaField(STRING_CODER_FIELD);
 274                     b.addPush(JavaKind.Int, LoadFieldNode.create(b.getConstantFieldProvider(), b.getConstantReflection(), b.getMetaAccess(),
 275                                     b.getOptions(), b.getAssumptions(), value, field, false, false));
 276                     return true;
 277                 }
 278             });


 541         });
 542         r.register1("doubleToLongBits", double.class, new InvocationPlugin() {
 543             @Override
 544             public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) {
 545                 LogicNode notNan = b.append(FloatEqualsNode.create(value, value, NodeView.DEFAULT));
 546                 ValueNode raw = b.append(ReinterpretNode.create(JavaKind.Long, value, NodeView.DEFAULT));
 547                 ValueNode result = b.append(ConditionalNode.create(notNan, raw, ConstantNode.forLong(0x7ff8000000000000L), NodeView.DEFAULT));
 548                 b.push(JavaKind.Long, result);
 549                 return true;
 550             }
 551         });
 552         r.register1("longBitsToDouble", long.class, new InvocationPlugin() {
 553             @Override
 554             public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) {
 555                 b.push(JavaKind.Double, b.append(ReinterpretNode.create(JavaKind.Double, value, NodeView.DEFAULT)));
 556                 return true;
 557             }
 558         });
 559     }
 560 
 561     public enum IntegerExactOp {
 562         INTEGER_ADD_EXACT,
 563         INTEGER_INCREMENT_EXACT,
 564         INTEGER_SUBTRACT_EXACT,
 565         INTEGER_DECREMENT_EXACT,
 566         INTEGER_MULTIPLY_EXACT
 567     }
 568 
 569     private static GuardingNode createIntegerExactArithmeticGuardNode(GraphBuilderContext b, ValueNode x, ValueNode y, IntegerExactOp op) {
 570         LogicNode overflowCheck;
 571         switch (op) {
 572             case INTEGER_ADD_EXACT:
 573             case INTEGER_INCREMENT_EXACT: {
 574                 overflowCheck = new IntegerAddExactOverflowNode(x, y);
 575                 break;
 576             }
 577             case INTEGER_SUBTRACT_EXACT:
 578             case INTEGER_DECREMENT_EXACT: {
 579                 overflowCheck = new IntegerSubExactOverflowNode(x, y);
 580                 break;
 581             }
 582             case INTEGER_MULTIPLY_EXACT: {
 583                 overflowCheck = new IntegerMulExactOverflowNode(x, y);
 584                 break;
 585             }
 586             default:
 587                 throw GraalError.shouldNotReachHere("Unknown integer exact operation.");
 588         }
 589         return b.add(new FixedGuardNode(overflowCheck, DeoptimizationReason.ArithmeticException, DeoptimizationAction.InvalidateRecompile, true));
 590     }
 591 
 592     private static ValueNode createIntegerExactArithmeticNode(GraphBuilderContext b, ValueNode x, ValueNode y, IntegerExactOp op) {
 593         switch (op) {
 594             case INTEGER_ADD_EXACT:
 595             case INTEGER_INCREMENT_EXACT:
 596                 return new IntegerAddExactNode(x, y, createIntegerExactArithmeticGuardNode(b, x, y, op));
 597             case INTEGER_SUBTRACT_EXACT:
 598             case INTEGER_DECREMENT_EXACT:
 599                 return new IntegerSubExactNode(x, y, createIntegerExactArithmeticGuardNode(b, x, y, op));
 600             case INTEGER_MULTIPLY_EXACT:
 601                 return new IntegerMulExactNode(x, y, createIntegerExactArithmeticGuardNode(b, x, y, op));
 602             default:
 603                 throw GraalError.shouldNotReachHere("Unknown integer exact operation.");
 604         }
 605     }
 606 
 607     private static IntegerExactArithmeticSplitNode createIntegerExactSplit(ValueNode x, ValueNode y, AbstractBeginNode exceptionEdge, IntegerExactOp op) {
 608         switch (op) {
 609             case INTEGER_ADD_EXACT:
 610             case INTEGER_INCREMENT_EXACT:
 611                 return new IntegerAddExactSplitNode(x.stamp(NodeView.DEFAULT).unrestricted(), x, y, null, exceptionEdge);
 612             case INTEGER_SUBTRACT_EXACT:
 613             case INTEGER_DECREMENT_EXACT:
 614                 return new IntegerSubExactSplitNode(x.stamp(NodeView.DEFAULT).unrestricted(), x, y, null, exceptionEdge);
 615             case INTEGER_MULTIPLY_EXACT:
 616                 return new IntegerMulExactSplitNode(x.stamp(NodeView.DEFAULT).unrestricted(), x, y, null, exceptionEdge);
 617             default:
 618                 throw GraalError.shouldNotReachHere("Unknown integer exact operation.");
 619         }
 620     }
 621 
 622     private static void createIntegerExactOperation(GraphBuilderContext b, JavaKind kind, ValueNode x, ValueNode y, IntegerExactOp op) {
 623         if (b.needsExplicitException()) {
 624             BytecodeExceptionKind exceptionKind = kind == JavaKind.Int ? BytecodeExceptionKind.INTEGER_EXACT_OVERFLOW : BytecodeExceptionKind.LONG_EXACT_OVERFLOW;
 625             AbstractBeginNode exceptionEdge = b.genExplicitExceptionEdge(exceptionKind);
 626             IntegerExactArithmeticSplitNode split = b.addPush(kind, createIntegerExactSplit(x, y, exceptionEdge, op));
 627             split.setNext(b.add(new BeginNode()));
 628         } else {
 629             b.addPush(kind, createIntegerExactArithmeticNode(b, x, y, op));
 630         }

 631     }
 632 
 633     private static void registerMathPlugins(InvocationPlugins plugins, boolean allowDeoptimization) {
 634         Registration r = new Registration(plugins, Math.class);
 635         if (allowDeoptimization) {
 636             for (JavaKind kind : new JavaKind[]{JavaKind.Int, JavaKind.Long}) {
 637                 Class<?> type = kind.toJavaClass();

 638                 r.register1("decrementExact", type, new InvocationPlugin() {
 639                     @Override
 640                     public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode x) {
 641                         ConstantNode y = b.add(ConstantNode.forIntegerKind(kind, 1));
 642                         createIntegerExactOperation(b, kind, x, y, IntegerExactOp.INTEGER_DECREMENT_EXACT);
 643                         return true;
 644                     }
 645                 });
 646 
 647                 r.register1("incrementExact", type, new InvocationPlugin() {
 648                     @Override
 649                     public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode x) {
 650                         ConstantNode y = b.add(ConstantNode.forIntegerKind(kind, 1));
 651                         createIntegerExactOperation(b, kind, x, y, IntegerExactOp.INTEGER_INCREMENT_EXACT);
 652                         return true;
 653                     }
 654                 });

 655                 r.register2("addExact", type, type, new InvocationPlugin() {
 656                     @Override
 657                     public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode x, ValueNode y) {
 658                         createIntegerExactOperation(b, kind, x, y, IntegerExactOp.INTEGER_ADD_EXACT);
 659                         return true;
 660                     }
 661                 });

 662                 r.register2("subtractExact", type, type, new InvocationPlugin() {
 663                     @Override
 664                     public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode x, ValueNode y) {
 665                         createIntegerExactOperation(b, kind, x, y, IntegerExactOp.INTEGER_SUBTRACT_EXACT);
 666                         return true;
 667                     }
 668                 });
 669 
 670                 r.register2("multiplyExact", type, type, new InvocationPlugin() {
 671                     @Override
 672                     public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode x, ValueNode y) {
 673                         createIntegerExactOperation(b, kind, x, y, IntegerExactOp.INTEGER_MULTIPLY_EXACT);
 674                         return true;
 675                     }
 676                 });
 677             }
 678         }
 679         r.register1("abs", Float.TYPE, new InvocationPlugin() {
 680 
 681             @Override
 682             public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) {
 683                 b.push(JavaKind.Float, b.append(new AbsNode(value).canonical(null)));
 684                 return true;
 685             }
 686         });
 687         r.register1("abs", Double.TYPE, new InvocationPlugin() {
 688             @Override
 689             public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) {
 690                 b.push(JavaKind.Double, b.append(new AbsNode(value).canonical(null)));
 691                 return true;
 692             }
 693         });
 694         r.register1("sqrt", Double.TYPE, new MathSqrtPlugin());
 695     }


1145         }
1146     }
1147 
1148     public static class UnsafeFencePlugin implements InvocationPlugin {
1149 
1150         private final int barriers;
1151 
1152         public UnsafeFencePlugin(int barriers) {
1153             this.barriers = barriers;
1154         }
1155 
1156         @Override
1157         public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver unsafe) {
1158             // Emits a null-check for the otherwise unused receiver
1159             unsafe.get();
1160             b.add(new MembarNode(barriers));
1161             return true;
1162         }
1163     }
1164 
1165     private static final SpeculationReasonGroup DIRECTIVE_SPECULATIONS = new SpeculationReasonGroup("GraalDirective", BytecodePosition.class);
















1166 
1167     private static void registerGraalDirectivesPlugins(InvocationPlugins plugins) {
1168         Registration r = new Registration(plugins, GraalDirectives.class);
1169         r.register0("deoptimize", new InvocationPlugin() {
1170             @Override
1171             public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
1172                 b.add(new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.TransferToInterpreter));
1173                 return true;
1174             }
1175         });
1176 
1177         r.register0("deoptimizeAndInvalidate", new InvocationPlugin() {
1178             @Override
1179             public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
1180                 b.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TransferToInterpreter));
1181                 return true;
1182             }
1183         });
1184 
1185         r.register0("deoptimizeAndInvalidateWithSpeculation", new InvocationPlugin() {
1186             @Override
1187             public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
1188                 GraalError.guarantee(b.getGraph().getSpeculationLog() != null, "A speculation log is needed to use `deoptimizeAndInvalidateWithSpeculation`");
1189                 BytecodePosition pos = new BytecodePosition(null, b.getMethod(), b.bci());
1190                 SpeculationReason reason = DIRECTIVE_SPECULATIONS.createSpeculationReason(pos);
1191                 Speculation speculation;
1192                 if (b.getGraph().getSpeculationLog().maySpeculate(reason)) {
1193                     speculation = b.getGraph().getSpeculationLog().speculate(reason);
1194                 } else {
1195                     speculation = SpeculationLog.NO_SPECULATION;
1196                 }
1197                 b.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TransferToInterpreter, speculation));
1198                 return true;
1199             }
1200         });
1201 
1202         r.register0("inCompiledCode", new InvocationPlugin() {
1203             @Override
1204             public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
1205                 b.addPush(JavaKind.Boolean, ConstantNode.forBoolean(true));
1206                 return true;
1207             }
1208         });
1209 
1210         r.register0("controlFlowAnchor", new InvocationPlugin() {


1353             }
1354 
1355             @Override
1356             public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode result, ValueNode counters) {
1357                 if (result.isConstant()) {
1358                     b.push(JavaKind.Boolean, result);
1359                     return true;
1360                 }
1361                 if (counters.isConstant()) {
1362                     ValueNode newResult = result;
1363                     int[] ctrs = snippetReflection.asObject(int[].class, (JavaConstant) counters.asConstant());
1364                     if (ctrs != null && ctrs.length == 2) {
1365                         int falseCount = ctrs[0];
1366                         int trueCount = ctrs[1];
1367                         int totalCount = trueCount + falseCount;
1368 
1369                         if (totalCount == 0) {
1370                             b.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TransferToInterpreter));
1371                         } else if (falseCount == 0 || trueCount == 0) {
1372                             boolean expected = falseCount == 0;
1373                             LogicNode condition = b.add(
1374                                             IntegerEqualsNode.create(b.getConstantReflection(), b.getMetaAccess(), b.getOptions(), null, result, b.add(ConstantNode.forBoolean(!expected)),
1375                                                             NodeView.DEFAULT));
1376                             b.append(new FixedGuardNode(condition, DeoptimizationReason.UnreachedCode, DeoptimizationAction.InvalidateReprofile, true));
1377                             newResult = b.add(ConstantNode.forBoolean(expected));
1378                         } else {
1379                             // We cannot use BranchProbabilityNode here since there's no guarantee
1380                             // the result of MethodHandleImpl.profileBoolean() is used as the
1381                             // test in an `if` statement (as required by BranchProbabilityNode).
1382                         }
1383                     }
1384                     b.addPush(JavaKind.Boolean, newResult);
1385                     return true;
1386                 }
1387                 b.addPush(JavaKind.Boolean,
1388                                 new ProfileBooleanNode(snippetReflection, b.getInvokeKind(), targetMethod, b.bci(), b.getInvokeReturnStamp(b.getAssumptions()), result, counters));
1389                 return true;
1390             }
1391         });
1392     }
1393 
< prev index next >