src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File hotspot Sdiff src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java

Print this page


   1 /*
   2  * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  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 package org.graalvm.compiler.hotspot.phases.aot;
  24 
  25 import static org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph.strictlyDominates;
  26 import static org.graalvm.compiler.hotspot.nodes.aot.LoadMethodCountersNode.getLoadMethodCountersNodes;
  27 import static org.graalvm.compiler.nodes.ConstantNode.getConstantNodes;
  28 
  29 import java.util.HashSet;
  30 import java.util.List;
  31 
  32 import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
  33 import jdk.vm.ci.hotspot.HotSpotObjectConstant;
  34 import jdk.vm.ci.hotspot.HotSpotResolvedJavaType;
  35 import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
  36 import jdk.vm.ci.meta.Constant;
  37 import jdk.vm.ci.meta.ConstantReflectionProvider;
  38 import jdk.vm.ci.meta.ResolvedJavaType;
  39 
  40 import org.graalvm.compiler.core.common.cfg.BlockMap;
  41 import org.graalvm.compiler.core.common.type.ObjectStamp;
  42 import org.graalvm.compiler.core.common.type.Stamp;
  43 import org.graalvm.compiler.core.common.type.StampFactory;
  44 import org.graalvm.compiler.debug.GraalError;
  45 import org.graalvm.compiler.graph.Node;
  46 import org.graalvm.compiler.graph.NodeMap;
  47 import org.graalvm.compiler.hotspot.FingerprintUtil;
  48 import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction;
  49 import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode;
  50 import org.graalvm.compiler.hotspot.nodes.aot.LoadConstantIndirectlyFixedNode;
  51 import org.graalvm.compiler.hotspot.nodes.aot.LoadConstantIndirectlyNode;
  52 import org.graalvm.compiler.hotspot.nodes.aot.LoadMethodCountersNode;
  53 import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode;
  54 import org.graalvm.compiler.hotspot.nodes.aot.ResolveMethodAndLoadCountersNode;


  55 import org.graalvm.compiler.nodes.ConstantNode;

  56 import org.graalvm.compiler.nodes.FixedWithNextNode;




  57 import org.graalvm.compiler.nodes.StructuredGraph;
  58 import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult;
  59 import org.graalvm.compiler.nodes.ValueNode;

  60 import org.graalvm.compiler.nodes.cfg.Block;
  61 import org.graalvm.compiler.phases.BasePhase;


  62 import org.graalvm.compiler.phases.schedule.SchedulePhase;
  63 import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy;
  64 import org.graalvm.compiler.phases.tiers.PhaseContext;
  65 import org.graalvm.util.EconomicMap;
  66 









  67 public class ReplaceConstantNodesPhase extends BasePhase<PhaseContext> {
  68 
  69     private static final HashSet<Class<?>> builtIns = new HashSet<>();
  70     private final boolean verifyFingerprints;
  71 
  72     static {
  73         builtIns.add(Boolean.class);
  74 
  75         Class<?> characterCacheClass = Character.class.getDeclaredClasses()[0];
  76         assert "java.lang.Character$CharacterCache".equals(characterCacheClass.getName());
  77         builtIns.add(characterCacheClass);
  78 
  79         Class<?> byteCacheClass = Byte.class.getDeclaredClasses()[0];
  80         assert "java.lang.Byte$ByteCache".equals(byteCacheClass.getName());
  81         builtIns.add(byteCacheClass);
  82 
  83         Class<?> shortCacheClass = Short.class.getDeclaredClasses()[0];
  84         assert "java.lang.Short$ShortCache".equals(shortCacheClass.getName());
  85         builtIns.add(shortCacheClass);
  86 


  98         return n instanceof LoadConstantIndirectlyNode      ||
  99                n instanceof LoadConstantIndirectlyFixedNode ||
 100                n instanceof ResolveConstantNode             ||
 101                n instanceof InitializeKlassNode;
 102         // @formatter:on
 103     }
 104 
 105     private static boolean anyUsagesNeedReplacement(ConstantNode node) {
 106         return node.usages().filter(n -> !isReplacementNode(n)).isNotEmpty();
 107     }
 108 
 109     private static boolean anyUsagesNeedReplacement(LoadMethodCountersNode node) {
 110         return node.usages().filter(n -> !(n instanceof ResolveMethodAndLoadCountersNode)).isNotEmpty();
 111     }
 112 
 113     private static boolean checkForBadFingerprint(HotSpotResolvedJavaType type) {
 114         if (type.isArray()) {
 115             if (type.getElementalType().isPrimitive()) {
 116                 return false;
 117             }
 118             return FingerprintUtil.getFingerprint((HotSpotResolvedObjectType) (type.getElementalType())) == 0;
 119         }
 120         return FingerprintUtil.getFingerprint((HotSpotResolvedObjectType) type) == 0;
 121     }
 122 
 123     /**
 124      * Replace {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} with indirection.


 125      *
 126      * @param graph
 127      * @param node {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} that needs
 128      *            resolution.

 129      */
 130     private void handleHotSpotMetaspaceConstant(StructuredGraph graph, ConstantNode node) {
 131         HotSpotMetaspaceConstant metaspaceConstant = (HotSpotMetaspaceConstant) node.asConstant();
 132         HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) metaspaceConstant.asResolvedJavaType();
 133 
 134         if (type != null) {
 135             if (verifyFingerprints && checkForBadFingerprint(type)) {
 136                 throw new GraalError("Type with bad fingerprint: " + type);
 137             }
 138             assert !metaspaceConstant.isCompressed() : "No support for replacing compressed metaspace constants";
 139             tryToReplaceWithExisting(graph, node);
 140             if (anyUsagesNeedReplacement(node)) {
 141                 replaceWithResolution(graph, node);
 142             }
 143         } else {
 144             throw new GraalError("Unsupported metaspace constant type: " + type);
 145         }














 146     }
 147 
 148     /**
 149      * Find the lowest dominating {@link FixedWithNextNode} before given node.

 150      *
 151      * @param graph
 152      * @param node
 153      * @return the last {@link FixedWithNextNode} that is scheduled before node.
 154      */
 155     private static FixedWithNextNode findFixedWithNextBefore(StructuredGraph graph, Node node) {
 156         ScheduleResult schedule = graph.getLastSchedule();
 157         NodeMap<Block> nodeToBlock = schedule.getNodeToBlockMap();
 158         BlockMap<List<Node>> blockToNodes = schedule.getBlockToNodesMap();
 159 
 160         Block block = nodeToBlock.get(node);

 161         FixedWithNextNode result = null;
 162         for (Node n : blockToNodes.get(block)) {
 163             if (n instanceof FixedWithNextNode) {
 164                 result = (FixedWithNextNode) n;
 165             }
 166             if (n.equals(node)) {
 167                 break;
 168             }



 169         }
 170         assert result != null;
 171         return result;
 172     }
 173 
 174     /**










































































































 175      * Try to find dominating node doing the resolution that can be reused.
 176      *
 177      * @param graph
 178      * @param node {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} that needs
 179      *            resolution.
 180      */
 181     private static void tryToReplaceWithExisting(StructuredGraph graph, ConstantNode node) {
 182         ScheduleResult schedule = graph.getLastSchedule();
 183         NodeMap<Block> nodeToBlock = schedule.getNodeToBlockMap();
 184         BlockMap<List<Node>> blockToNodes = schedule.getBlockToNodesMap();
 185 
 186         EconomicMap<Block, Node> blockToExisting = EconomicMap.create();
 187         for (Node n : node.usages().filter(n -> isReplacementNode(n))) {
 188             blockToExisting.put(nodeToBlock.get(n), n);
 189         }
 190         for (Node use : node.usages().filter(n -> !isReplacementNode(n)).snapshot()) {
 191             boolean replaced = false;
 192             Block b = nodeToBlock.get(use);
 193             Node e = blockToExisting.get(b);
 194             if (e != null) {


 206                     }
 207                 }
 208             }
 209             if (!replaced) {
 210                 // Look for dominating blocks that have existing nodes
 211                 for (Block d : blockToExisting.getKeys()) {
 212                     if (strictlyDominates(d, b)) {
 213                         use.replaceFirstInput(node, blockToExisting.get(d));
 214                         break;
 215                     }
 216                 }
 217             }
 218         }
 219     }
 220 
 221     /**
 222      * Replace the uses of a constant with either {@link LoadConstantIndirectlyNode} or
 223      * {@link ResolveConstantNode}.
 224      *
 225      * @param graph

 226      * @param node {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} that needs
 227      *            resolution.
 228      */
 229     private static void replaceWithResolution(StructuredGraph graph, ConstantNode node) {
 230         HotSpotMetaspaceConstant metaspaceConstant = (HotSpotMetaspaceConstant) node.asConstant();
 231         HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) metaspaceConstant.asResolvedJavaType();
 232         ResolvedJavaType topMethodHolder = graph.method().getDeclaringClass();
 233         ValueNode replacement;
 234 
 235         if (type.isArray() && type.getComponentType().isPrimitive()) {
 236             // Special case for primitive arrays. The AOT runtime pre-resolves them, so we may
 237             // omit the resolution call.
 238             replacement = graph.addOrUnique(new LoadConstantIndirectlyNode(node));
 239         } else if (type.equals(topMethodHolder) || (type.isAssignableFrom(topMethodHolder) && !type.isInterface())) {
 240             // If it's a supertype of or the same class that declares the top method, we are
 241             // guaranteed to have it resolved already. If it's an interface, we just test for
 242             // equality.
 243             replacement = graph.addOrUnique(new LoadConstantIndirectlyNode(node));
 244         } else {
 245             FixedWithNextNode fixedReplacement;
 246             if (builtIns.contains(type.mirror())) {
 247                 // Special case of klass constants that come from {@link BoxingSnippets}.
 248                 fixedReplacement = graph.add(new ResolveConstantNode(node, HotSpotConstantLoadAction.INITIALIZE));
 249             } else {
 250                 fixedReplacement = graph.add(new ResolveConstantNode(node));
 251             }
 252             graph.addAfterFixed(findFixedWithNextBefore(graph, node), fixedReplacement);
 253             replacement = fixedReplacement;
 254         }
 255         node.replaceAtUsages(replacement, n -> !isReplacementNode(n));
 256     }
 257 
 258     /**


























 259      * Replace an object constant with an indirect load {@link ResolveConstantNode}. Currently we
 260      * support only strings.
 261      *
 262      * @param graph

 263      * @param node {@link ConstantNode} containing a {@link HotSpotObjectConstant} that needs
 264      *            resolution.
 265      */
 266     private static void handleHotSpotObjectConstant(StructuredGraph graph, ConstantNode node) {
 267         HotSpotObjectConstant constant = (HotSpotObjectConstant) node.asJavaConstant();
 268         HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) constant.getType();
 269         if (type.mirror().equals(String.class)) {
 270             assert !constant.isCompressed() : "No support for replacing compressed oop constants";
 271             FixedWithNextNode replacement = graph.add(new ResolveConstantNode(node));
 272             graph.addAfterFixed(findFixedWithNextBefore(graph, node), replacement);
 273             node.replaceAtUsages(replacement, n -> !(n instanceof ResolveConstantNode));
 274         } else {
 275             throw new GraalError("Unsupported object constant type: " + type);
 276         }
 277     }
 278 
 279     /**
 280      * Replace {@link LoadMethodCountersNode} with indirect load
 281      * {@link ResolveMethodAndLoadCountersNode}, expose a klass constant of the holder.
 282      *
 283      * @param graph

 284      * @param node
 285      * @param context
 286      */
 287     private static void handleLoadMethodCounters(StructuredGraph graph, LoadMethodCountersNode node, PhaseContext context) {
 288         ResolvedJavaType type = node.getMethod().getDeclaringClass();
 289         Stamp hubStamp = context.getStampProvider().createHubStamp((ObjectStamp) StampFactory.objectNonNull());
 290         ConstantReflectionProvider constantReflection = context.getConstantReflection();
 291         ConstantNode klassHint = ConstantNode.forConstant(hubStamp, constantReflection.asObjectHub(type), context.getMetaAccess(), graph);
 292         FixedWithNextNode replacement = graph.add(new ResolveMethodAndLoadCountersNode(node.getMethod(), klassHint));
 293         graph.addAfterFixed(findFixedWithNextBefore(graph, node), replacement);
 294         node.replaceAtUsages(replacement, n -> !(n instanceof ResolveMethodAndLoadCountersNode));
 295     }
 296 
 297     /**
 298      * Replace {@link LoadMethodCountersNode} with {@link ResolveMethodAndLoadCountersNode}, expose
 299      * klass constants.
 300      *
 301      * @param graph

 302      * @param context
 303      */
 304     private static void replaceLoadMethodCounters(StructuredGraph graph, PhaseContext context) {
 305         new SchedulePhase(SchedulingStrategy.LATEST_OUT_OF_LOOPS, true).apply(graph, false);

 306         for (LoadMethodCountersNode node : getLoadMethodCountersNodes(graph)) {
 307             if (anyUsagesNeedReplacement(node)) {
 308                 handleLoadMethodCounters(graph, node, context);
 309             }
 310         }
 311     }
 312 
 313     /**
 314      * Replace object and klass constants with resolution nodes or reuse preceding initializations.
 315      *
 316      * @param graph

 317      */
 318     private void replaceKlassesAndObjects(StructuredGraph graph) {
 319         new SchedulePhase(SchedulingStrategy.LATEST_OUT_OF_LOOPS, true).apply(graph, false);
 320 
 321         for (ConstantNode node : getConstantNodes(graph)) {
 322             Constant constant = node.asConstant();
 323             if (constant instanceof HotSpotMetaspaceConstant && anyUsagesNeedReplacement(node)) {
 324                 handleHotSpotMetaspaceConstant(graph, node);
 325             } else if (constant instanceof HotSpotObjectConstant && anyUsagesNeedReplacement(node)) {
 326                 handleHotSpotObjectConstant(graph, node);
 327             }
 328         }
 329     }
 330 
 331     @Override
 332     protected void run(StructuredGraph graph, PhaseContext context) {



 333         // Replace LoadMethodCountersNode with ResolveMethodAndLoadCountersNode, expose klass
 334         // constants.
 335         replaceLoadMethodCounters(graph, context);
 336 
 337         // Replace object and klass constants (including the ones added in the previous pass) with
 338         // resolution nodes.
 339         replaceKlassesAndObjects(graph);
 340     }
 341 
 342     @Override
 343     public boolean checkContract() {
 344         return false;
 345     }
 346 
 347     public ReplaceConstantNodesPhase() {
 348         this(true);
 349     }
 350 
 351     public ReplaceConstantNodesPhase(boolean verifyFingerprints) {
 352         this.verifyFingerprints = verifyFingerprints;
 353     }
 354 }
   1 /*
   2  * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  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 package org.graalvm.compiler.hotspot.phases.aot;
  24 
  25 import static org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph.strictlyDominates;
  26 import static org.graalvm.compiler.hotspot.nodes.aot.LoadMethodCountersNode.getLoadMethodCountersNodes;
  27 import static org.graalvm.compiler.nodes.ConstantNode.getConstantNodes;
  28 
  29 import java.util.HashSet;
  30 import java.util.List;
  31 








  32 import org.graalvm.compiler.core.common.cfg.BlockMap;
  33 import org.graalvm.compiler.core.common.type.ObjectStamp;
  34 import org.graalvm.compiler.core.common.type.Stamp;
  35 import org.graalvm.compiler.core.common.type.StampFactory;
  36 import org.graalvm.compiler.debug.GraalError;
  37 import org.graalvm.compiler.graph.Node;
  38 import org.graalvm.compiler.graph.NodeMap;

  39 import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction;
  40 import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode;
  41 import org.graalvm.compiler.hotspot.nodes.aot.LoadConstantIndirectlyFixedNode;
  42 import org.graalvm.compiler.hotspot.nodes.aot.LoadConstantIndirectlyNode;
  43 import org.graalvm.compiler.hotspot.nodes.aot.LoadMethodCountersNode;
  44 import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode;
  45 import org.graalvm.compiler.hotspot.nodes.aot.ResolveMethodAndLoadCountersNode;
  46 import org.graalvm.compiler.nodes.AbstractBeginNode;
  47 import org.graalvm.compiler.nodes.AbstractMergeNode;
  48 import org.graalvm.compiler.nodes.ConstantNode;
  49 import org.graalvm.compiler.nodes.FixedNode;
  50 import org.graalvm.compiler.nodes.FixedWithNextNode;
  51 import org.graalvm.compiler.nodes.FrameState;
  52 import org.graalvm.compiler.nodes.LoopBeginNode;
  53 import org.graalvm.compiler.nodes.LoopExitNode;
  54 import org.graalvm.compiler.nodes.StateSplit;
  55 import org.graalvm.compiler.nodes.StructuredGraph;
  56 import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult;
  57 import org.graalvm.compiler.nodes.ValueNode;
  58 import org.graalvm.compiler.nodes.calc.FloatingNode;
  59 import org.graalvm.compiler.nodes.cfg.Block;
  60 import org.graalvm.compiler.phases.BasePhase;
  61 import org.graalvm.compiler.phases.graph.ReentrantNodeIterator;
  62 import org.graalvm.compiler.phases.graph.ReentrantNodeIterator.NodeIteratorClosure;
  63 import org.graalvm.compiler.phases.schedule.SchedulePhase;
  64 import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy;
  65 import org.graalvm.compiler.phases.tiers.PhaseContext;
  66 import org.graalvm.util.EconomicMap;
  67 
  68 import jdk.vm.ci.code.BytecodeFrame;
  69 import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
  70 import jdk.vm.ci.hotspot.HotSpotObjectConstant;
  71 import jdk.vm.ci.hotspot.HotSpotResolvedJavaType;
  72 import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
  73 import jdk.vm.ci.meta.Constant;
  74 import jdk.vm.ci.meta.ConstantReflectionProvider;
  75 import jdk.vm.ci.meta.ResolvedJavaType;
  76 
  77 public class ReplaceConstantNodesPhase extends BasePhase<PhaseContext> {
  78 
  79     private static final HashSet<Class<?>> builtIns = new HashSet<>();
  80     private final boolean verifyFingerprints;
  81 
  82     static {
  83         builtIns.add(Boolean.class);
  84 
  85         Class<?> characterCacheClass = Character.class.getDeclaredClasses()[0];
  86         assert "java.lang.Character$CharacterCache".equals(characterCacheClass.getName());
  87         builtIns.add(characterCacheClass);
  88 
  89         Class<?> byteCacheClass = Byte.class.getDeclaredClasses()[0];
  90         assert "java.lang.Byte$ByteCache".equals(byteCacheClass.getName());
  91         builtIns.add(byteCacheClass);
  92 
  93         Class<?> shortCacheClass = Short.class.getDeclaredClasses()[0];
  94         assert "java.lang.Short$ShortCache".equals(shortCacheClass.getName());
  95         builtIns.add(shortCacheClass);
  96 


 108         return n instanceof LoadConstantIndirectlyNode      ||
 109                n instanceof LoadConstantIndirectlyFixedNode ||
 110                n instanceof ResolveConstantNode             ||
 111                n instanceof InitializeKlassNode;
 112         // @formatter:on
 113     }
 114 
 115     private static boolean anyUsagesNeedReplacement(ConstantNode node) {
 116         return node.usages().filter(n -> !isReplacementNode(n)).isNotEmpty();
 117     }
 118 
 119     private static boolean anyUsagesNeedReplacement(LoadMethodCountersNode node) {
 120         return node.usages().filter(n -> !(n instanceof ResolveMethodAndLoadCountersNode)).isNotEmpty();
 121     }
 122 
 123     private static boolean checkForBadFingerprint(HotSpotResolvedJavaType type) {
 124         if (type.isArray()) {
 125             if (type.getElementalType().isPrimitive()) {
 126                 return false;
 127             }
 128             return ((HotSpotResolvedObjectType) (type.getElementalType())).getFingerprint() == 0;
 129         }
 130         return ((HotSpotResolvedObjectType) type).getFingerprint() == 0;
 131     }
 132 
 133     /**
 134      * Insert the replacement node into the graph. We may need to insert it into a place different
 135      * than the original {@link FloatingNode} since we need to make sure that replacement will have
 136      * a valid state assigned.
 137      *
 138      * @param graph
 139      * @param stateMapper
 140      * @param node
 141      * @param replacement
 142      */
 143     private static void insertReplacement(StructuredGraph graph, FrameStateMapperClosure stateMapper, FloatingNode node, FixedWithNextNode replacement) {
 144         FixedWithNextNode insertionPoint = findInsertionPoint(graph, stateMapper, node);
 145         graph.addAfterFixed(insertionPoint, replacement);
 146         stateMapper.addState(replacement, stateMapper.getState(insertionPoint));











 147     }
 148 
 149     /**
 150      * Find a good place to insert a stateful fixed node that is above the given node. A good
 151      * insertion point should have a valid FrameState reaching it.
 152      *
 153      * @param graph
 154      * @param stateMapper
 155      * @param node start search from this node up
 156      * @return an insertion point
 157      */
 158     private static FixedWithNextNode findInsertionPoint(StructuredGraph graph, FrameStateMapperClosure stateMapper, FloatingNode node) {
 159         FixedWithNextNode fixed = findFixedBeforeFloating(graph, node);
 160         FixedWithNextNode result = findFixedWithValidState(graph, stateMapper, fixed);
 161         return result;
 162     }
 163 
 164     /**
 165      * Find the first {@link FixedWithNextNode} that is currently scheduled before the given
 166      * floating node.
 167      *
 168      * @param graph
 169      * @param node start search from this node up
 170      * @return the first {@link FixedWithNextNode}
 171      */
 172     private static FixedWithNextNode findFixedBeforeFloating(StructuredGraph graph, FloatingNode node) {
 173         ScheduleResult schedule = graph.getLastSchedule();
 174         NodeMap<Block> nodeToBlock = schedule.getNodeToBlockMap();


 175         Block block = nodeToBlock.get(node);
 176         BlockMap<List<Node>> blockToNodes = schedule.getBlockToNodesMap();
 177         FixedWithNextNode result = null;
 178         for (Node n : blockToNodes.get(block)) {



 179             if (n.equals(node)) {
 180                 break;
 181             }
 182             if (n instanceof FixedWithNextNode) {
 183                 result = (FixedWithNextNode) n;
 184             }
 185         }
 186         assert result != null;
 187         return result;
 188     }
 189 
 190     /**
 191      * Find first dominating {@link FixedWithNextNode} that has a valid state reaching it starting
 192      * from the given node.
 193      *
 194      * @param graph
 195      * @param stateMapper
 196      * @param node
 197      * @return {@link FixedWithNextNode} that we can use as an insertion point
 198      */
 199     private static FixedWithNextNode findFixedWithValidState(StructuredGraph graph, FrameStateMapperClosure stateMapper, FixedWithNextNode node) {
 200         ScheduleResult schedule = graph.getLastSchedule();
 201         NodeMap<Block> nodeToBlock = schedule.getNodeToBlockMap();
 202         Block block = nodeToBlock.get(node);
 203 
 204         Node n = node;
 205         do {
 206             if (isFixedWithValidState(stateMapper, n)) {
 207                 return (FixedWithNextNode) n;
 208             }
 209             while (n != block.getBeginNode()) {
 210                 n = n.predecessor();
 211                 if (isFixedWithValidState(stateMapper, n)) {
 212                     return (FixedWithNextNode) n;
 213                 }
 214             }
 215             block = block.getDominator();
 216             if (block != null) {
 217                 n = block.getEndNode();
 218             }
 219         } while (block != null);
 220 
 221         return graph.start();
 222     }
 223 
 224     private static boolean isFixedWithValidState(FrameStateMapperClosure stateMapper, Node n) {
 225         if (n instanceof FixedWithNextNode) {
 226             FixedWithNextNode fixed = (FixedWithNextNode) n;
 227             assert stateMapper.getState(fixed) != null;
 228             if (!BytecodeFrame.isPlaceholderBci(stateMapper.getState(fixed).bci)) {
 229                 return true;
 230             }
 231         }
 232         return false;
 233     }
 234 
 235     /**
 236      * Compute frame states for all fixed nodes in the graph.
 237      */
 238     private static class FrameStateMapperClosure extends NodeIteratorClosure<FrameState> {
 239         private NodeMap<FrameState> reachingStates;
 240 
 241         @Override
 242         protected FrameState processNode(FixedNode node, FrameState previousState) {
 243             FrameState currentState = previousState;
 244             if (node instanceof StateSplit) {
 245                 StateSplit stateSplit = (StateSplit) node;
 246                 FrameState stateAfter = stateSplit.stateAfter();
 247                 if (stateAfter != null) {
 248                     currentState = stateAfter;
 249                 }
 250             }
 251             reachingStates.put(node, currentState);
 252             return currentState;
 253         }
 254 
 255         @Override
 256         protected FrameState merge(AbstractMergeNode merge, List<FrameState> states) {
 257             FrameState singleFrameState = singleFrameState(states);
 258             FrameState currentState = singleFrameState == null ? merge.stateAfter() : singleFrameState;
 259             reachingStates.put(merge, currentState);
 260             return currentState;
 261         }
 262 
 263         @Override
 264         protected FrameState afterSplit(AbstractBeginNode node, FrameState oldState) {
 265             return oldState;
 266         }
 267 
 268         @Override
 269         protected EconomicMap<LoopExitNode, FrameState> processLoop(LoopBeginNode loop, FrameState initialState) {
 270             return ReentrantNodeIterator.processLoop(this, loop, initialState).exitStates;
 271         }
 272 
 273         private static FrameState singleFrameState(List<FrameState> states) {
 274             FrameState singleState = states.get(0);
 275             for (int i = 1; i < states.size(); ++i) {
 276                 if (states.get(i) != singleState) {
 277                     return null;
 278                 }
 279             }
 280             return singleState;
 281         }
 282 
 283         FrameStateMapperClosure(StructuredGraph graph) {
 284             reachingStates = new NodeMap<>(graph);
 285         }
 286 
 287         public FrameState getState(Node n) {
 288             return reachingStates.get(n);
 289         }
 290 
 291         public void addState(Node n, FrameState s) {
 292             reachingStates.setAndGrow(n, s);
 293         }
 294     }
 295 
 296     /**
 297      * Try to find dominating node doing the resolution that can be reused.
 298      *
 299      * @param graph
 300      * @param node {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} that needs
 301      *            resolution.
 302      */
 303     private static void tryToReplaceWithExisting(StructuredGraph graph, ConstantNode node) {
 304         ScheduleResult schedule = graph.getLastSchedule();
 305         NodeMap<Block> nodeToBlock = schedule.getNodeToBlockMap();
 306         BlockMap<List<Node>> blockToNodes = schedule.getBlockToNodesMap();
 307 
 308         EconomicMap<Block, Node> blockToExisting = EconomicMap.create();
 309         for (Node n : node.usages().filter(n -> isReplacementNode(n))) {
 310             blockToExisting.put(nodeToBlock.get(n), n);
 311         }
 312         for (Node use : node.usages().filter(n -> !isReplacementNode(n)).snapshot()) {
 313             boolean replaced = false;
 314             Block b = nodeToBlock.get(use);
 315             Node e = blockToExisting.get(b);
 316             if (e != null) {


 328                     }
 329                 }
 330             }
 331             if (!replaced) {
 332                 // Look for dominating blocks that have existing nodes
 333                 for (Block d : blockToExisting.getKeys()) {
 334                     if (strictlyDominates(d, b)) {
 335                         use.replaceFirstInput(node, blockToExisting.get(d));
 336                         break;
 337                     }
 338                 }
 339             }
 340         }
 341     }
 342 
 343     /**
 344      * Replace the uses of a constant with either {@link LoadConstantIndirectlyNode} or
 345      * {@link ResolveConstantNode}.
 346      *
 347      * @param graph
 348      * @param stateMapper
 349      * @param node {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} that needs
 350      *            resolution.
 351      */
 352     private static void replaceWithResolution(StructuredGraph graph, FrameStateMapperClosure stateMapper, ConstantNode node) {
 353         HotSpotMetaspaceConstant metaspaceConstant = (HotSpotMetaspaceConstant) node.asConstant();
 354         HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) metaspaceConstant.asResolvedJavaType();
 355         ResolvedJavaType topMethodHolder = graph.method().getDeclaringClass();
 356         ValueNode replacement;
 357 
 358         if (type.isArray() && type.getComponentType().isPrimitive()) {
 359             // Special case for primitive arrays. The AOT runtime pre-resolves them, so we may
 360             // omit the resolution call.
 361             replacement = graph.addOrUnique(new LoadConstantIndirectlyNode(node));
 362         } else if (type.equals(topMethodHolder) || (type.isAssignableFrom(topMethodHolder) && !type.isInterface())) {
 363             // If it's a supertype of or the same class that declares the top method, we are
 364             // guaranteed to have it resolved already. If it's an interface, we just test for
 365             // equality.
 366             replacement = graph.addOrUnique(new LoadConstantIndirectlyNode(node));
 367         } else {
 368             FixedWithNextNode fixedReplacement;
 369             if (builtIns.contains(type.mirror())) {
 370                 // Special case of klass constants that come from {@link BoxingSnippets}.
 371                 fixedReplacement = graph.add(new ResolveConstantNode(node, HotSpotConstantLoadAction.INITIALIZE));
 372             } else {
 373                 fixedReplacement = graph.add(new ResolveConstantNode(node));
 374             }
 375             insertReplacement(graph, stateMapper, node, fixedReplacement);
 376             replacement = fixedReplacement;
 377         }
 378         node.replaceAtUsages(replacement, n -> !isReplacementNode(n));
 379     }
 380 
 381     /**
 382      * Replace {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} with indirection.
 383      *
 384      * @param graph
 385      * @param stateMapper
 386      * @param node {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} that needs
 387      *            resolution.
 388      */
 389     private void handleHotSpotMetaspaceConstant(StructuredGraph graph, FrameStateMapperClosure stateMapper, ConstantNode node) {
 390         HotSpotMetaspaceConstant metaspaceConstant = (HotSpotMetaspaceConstant) node.asConstant();
 391         HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) metaspaceConstant.asResolvedJavaType();
 392 
 393         if (type != null) {
 394             if (verifyFingerprints && checkForBadFingerprint(type)) {
 395                 throw new GraalError("Type with bad fingerprint: " + type);
 396             }
 397             assert !metaspaceConstant.isCompressed() : "No support for replacing compressed metaspace constants";
 398             tryToReplaceWithExisting(graph, node);
 399             if (anyUsagesNeedReplacement(node)) {
 400                 replaceWithResolution(graph, stateMapper, node);
 401             }
 402         } else {
 403             throw new GraalError("Unsupported metaspace constant type: " + type);
 404         }
 405     }
 406 
 407     /**
 408      * Replace an object constant with an indirect load {@link ResolveConstantNode}. Currently we
 409      * support only strings.
 410      *
 411      * @param graph
 412      * @param stateMapper
 413      * @param node {@link ConstantNode} containing a {@link HotSpotObjectConstant} that needs
 414      *            resolution.
 415      */
 416     private static void handleHotSpotObjectConstant(StructuredGraph graph, FrameStateMapperClosure stateMapper, ConstantNode node) {
 417         HotSpotObjectConstant constant = (HotSpotObjectConstant) node.asJavaConstant();
 418         HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) constant.getType();
 419         if (type.mirror().equals(String.class)) {
 420             assert !constant.isCompressed() : "No support for replacing compressed oop constants";
 421             FixedWithNextNode replacement = graph.add(new ResolveConstantNode(node));
 422             insertReplacement(graph, stateMapper, node, replacement);
 423             node.replaceAtUsages(replacement, n -> !(n instanceof ResolveConstantNode));
 424         } else {
 425             throw new GraalError("Unsupported object constant type: " + type);
 426         }
 427     }
 428 
 429     /**
 430      * Replace {@link LoadMethodCountersNode} with indirect load
 431      * {@link ResolveMethodAndLoadCountersNode}, expose a klass constant of the holder.
 432      *
 433      * @param graph
 434      * @param stateMapper
 435      * @param node
 436      * @param context
 437      */
 438     private static void handleLoadMethodCounters(StructuredGraph graph, FrameStateMapperClosure stateMapper, LoadMethodCountersNode node, PhaseContext context) {
 439         ResolvedJavaType type = node.getMethod().getDeclaringClass();
 440         Stamp hubStamp = context.getStampProvider().createHubStamp((ObjectStamp) StampFactory.objectNonNull());
 441         ConstantReflectionProvider constantReflection = context.getConstantReflection();
 442         ConstantNode klassHint = ConstantNode.forConstant(hubStamp, constantReflection.asObjectHub(type), context.getMetaAccess(), graph);
 443         FixedWithNextNode replacement = graph.add(new ResolveMethodAndLoadCountersNode(node.getMethod(), klassHint));
 444         insertReplacement(graph, stateMapper, node, replacement);
 445         node.replaceAtUsages(replacement, n -> !(n instanceof ResolveMethodAndLoadCountersNode));
 446     }
 447 
 448     /**
 449      * Replace {@link LoadMethodCountersNode} with {@link ResolveMethodAndLoadCountersNode}, expose
 450      * klass constants.
 451      *
 452      * @param graph
 453      * @param stateMapper
 454      * @param context
 455      */
 456     private static void replaceLoadMethodCounters(StructuredGraph graph, FrameStateMapperClosure stateMapper, PhaseContext context) {
 457         new SchedulePhase(SchedulingStrategy.LATEST_OUT_OF_LOOPS, true).apply(graph, false);
 458 
 459         for (LoadMethodCountersNode node : getLoadMethodCountersNodes(graph)) {
 460             if (anyUsagesNeedReplacement(node)) {
 461                 handleLoadMethodCounters(graph, stateMapper, node, context);
 462             }
 463         }
 464     }
 465 
 466     /**
 467      * Replace object and klass constants with resolution nodes or reuse preceding initializations.
 468      *
 469      * @param graph
 470      * @param stateMapper
 471      */
 472     private void replaceKlassesAndObjects(StructuredGraph graph, FrameStateMapperClosure stateMapper) {
 473         new SchedulePhase(SchedulingStrategy.LATEST_OUT_OF_LOOPS, true).apply(graph, false);
 474 
 475         for (ConstantNode node : getConstantNodes(graph)) {
 476             Constant constant = node.asConstant();
 477             if (constant instanceof HotSpotMetaspaceConstant && anyUsagesNeedReplacement(node)) {
 478                 handleHotSpotMetaspaceConstant(graph, stateMapper, node);
 479             } else if (constant instanceof HotSpotObjectConstant && anyUsagesNeedReplacement(node)) {
 480                 handleHotSpotObjectConstant(graph, stateMapper, node);
 481             }
 482         }
 483     }
 484 
 485     @Override
 486     protected void run(StructuredGraph graph, PhaseContext context) {
 487         FrameStateMapperClosure stateMapper = new FrameStateMapperClosure(graph);
 488         ReentrantNodeIterator.apply(stateMapper, graph.start(), null);
 489 
 490         // Replace LoadMethodCountersNode with ResolveMethodAndLoadCountersNode, expose klass
 491         // constants.
 492         replaceLoadMethodCounters(graph, stateMapper, context);
 493 
 494         // Replace object and klass constants (including the ones added in the previous pass) with
 495         // resolution nodes.
 496         replaceKlassesAndObjects(graph, stateMapper);
 497     }
 498 
 499     @Override
 500     public boolean checkContract() {
 501         return false;
 502     }
 503 
 504     public ReplaceConstantNodesPhase() {
 505         this(true);
 506     }
 507 
 508     public ReplaceConstantNodesPhase(boolean verifyFingerprints) {
 509         this.verifyFingerprints = verifyFingerprints;
 510     }
 511 }
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File