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.replacements.aot; 24 25 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.VERY_SLOW_PATH_PROBABILITY; 26 import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability; 27 import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER; 28 29 import org.graalvm.compiler.api.replacements.Snippet; 30 import org.graalvm.compiler.debug.GraalError; 31 import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction; 32 import org.graalvm.compiler.hotspot.meta.HotSpotProviders; 33 import org.graalvm.compiler.hotspot.nodes.aot.EncodedSymbolNode; 34 import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode; 35 import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassStubCall; 36 import org.graalvm.compiler.hotspot.nodes.aot.LoadConstantIndirectlyNode; 37 import org.graalvm.compiler.hotspot.nodes.aot.LoadMethodCountersIndirectlyNode; 38 import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode; 39 import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantStubCall; 40 import org.graalvm.compiler.hotspot.nodes.aot.ResolveMethodAndLoadCountersNode; 41 import org.graalvm.compiler.hotspot.nodes.aot.ResolveMethodAndLoadCountersStubCall; 42 import org.graalvm.compiler.hotspot.nodes.type.MethodPointerStamp; 43 import org.graalvm.compiler.hotspot.word.KlassPointer; 44 import org.graalvm.compiler.hotspot.word.MethodCountersPointer; 45 import org.graalvm.compiler.hotspot.word.MethodPointer; 46 import org.graalvm.compiler.nodes.ConstantNode; 47 import org.graalvm.compiler.nodes.StructuredGraph; 48 import org.graalvm.compiler.nodes.ValueNode; 49 import org.graalvm.compiler.nodes.spi.LoweringTool; 50 import org.graalvm.compiler.nodes.util.GraphUtil; 51 import org.graalvm.compiler.replacements.SnippetTemplate; 52 import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; 53 import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; 54 import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; 55 import org.graalvm.compiler.replacements.Snippets; 56 57 import jdk.vm.ci.code.TargetDescription; 58 import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; 59 import jdk.vm.ci.hotspot.HotSpotObjectConstant; 60 import jdk.vm.ci.meta.Constant; 61 62 public class ResolveConstantSnippets implements Snippets { 63 64 @Snippet 65 public static Object resolveObjectConstant(Object constant) { 66 Object result = LoadConstantIndirectlyNode.loadObject(constant); 67 if (probability(VERY_SLOW_PATH_PROBABILITY, result == null)) { 68 result = ResolveConstantStubCall.resolveObject(constant, EncodedSymbolNode.encode(constant)); 69 } 70 return result; 71 } 72 73 @Snippet 74 public static KlassPointer resolveKlassConstant(KlassPointer constant) { 75 KlassPointer result = LoadConstantIndirectlyNode.loadKlass(constant); 76 if (probability(VERY_SLOW_PATH_PROBABILITY, result.isNull())) { 77 result = ResolveConstantStubCall.resolveKlass(constant, EncodedSymbolNode.encode(constant)); 78 } 79 return result; 80 } 81 82 @Snippet 83 public static MethodCountersPointer resolveMethodAndLoadCounters(MethodPointer method, KlassPointer klassHint) { 84 MethodCountersPointer result = LoadMethodCountersIndirectlyNode.loadMethodCounters(method); 85 if (probability(VERY_SLOW_PATH_PROBABILITY, result.isNull())) { 86 result = ResolveMethodAndLoadCountersStubCall.resolveMethodAndLoadCounters(method, klassHint, EncodedSymbolNode.encode(method)); 87 } 88 return result; 89 } 90 91 @Snippet 92 public static KlassPointer initializeKlass(KlassPointer constant) { 93 KlassPointer result = LoadConstantIndirectlyNode.loadKlass(constant, HotSpotConstantLoadAction.INITIALIZE); 94 if (probability(VERY_SLOW_PATH_PROBABILITY, result.isNull())) { 95 result = InitializeKlassStubCall.initializeKlass(constant, EncodedSymbolNode.encode(constant)); 96 } 97 return result; 98 } 99 100 @Snippet 101 public static KlassPointer pureInitializeKlass(KlassPointer constant) { 102 KlassPointer result = LoadConstantIndirectlyNode.loadKlass(constant, HotSpotConstantLoadAction.INITIALIZE); 103 if (probability(VERY_SLOW_PATH_PROBABILITY, result.isNull())) { 104 result = ResolveConstantStubCall.resolveKlass(constant, EncodedSymbolNode.encode(constant), HotSpotConstantLoadAction.INITIALIZE); 105 } 106 return result; 107 } 108 109 public static class Templates extends AbstractTemplates { 110 private final SnippetInfo resolveObjectConstant = snippet(ResolveConstantSnippets.class, "resolveObjectConstant"); 111 private final SnippetInfo resolveKlassConstant = snippet(ResolveConstantSnippets.class, "resolveKlassConstant"); 112 private final SnippetInfo resolveMethodAndLoadCounters = snippet(ResolveConstantSnippets.class, "resolveMethodAndLoadCounters"); 113 private final SnippetInfo initializeKlass = snippet(ResolveConstantSnippets.class, "initializeKlass"); 114 private final SnippetInfo pureInitializeKlass = snippet(ResolveConstantSnippets.class, "pureInitializeKlass"); 115 116 public Templates(HotSpotProviders providers, TargetDescription target) { 117 super(providers, providers.getSnippetReflection(), target); 118 } 119 120 public void lower(ResolveConstantNode resolveConstantNode, LoweringTool tool) { 121 StructuredGraph graph = resolveConstantNode.graph(); 122 123 ValueNode value = resolveConstantNode.value(); 124 assert value.isConstant() : "Expected a constant: " + value; 125 Constant constant = value.asConstant(); 126 SnippetInfo snippet = null; 127 128 if (constant instanceof HotSpotMetaspaceConstant) { 129 HotSpotMetaspaceConstant hotspotMetaspaceConstant = (HotSpotMetaspaceConstant) constant; 130 if (hotspotMetaspaceConstant.asResolvedJavaType() != null) { 131 if (resolveConstantNode.action() == HotSpotConstantLoadAction.RESOLVE) { 132 snippet = resolveKlassConstant; 133 } else { 134 assert resolveConstantNode.action() == HotSpotConstantLoadAction.INITIALIZE; 135 snippet = pureInitializeKlass; 136 } 137 } 138 } else if (constant instanceof HotSpotObjectConstant) { 139 snippet = resolveObjectConstant; 140 HotSpotObjectConstant hotspotObjectConstant = (HotSpotObjectConstant) constant; 141 assert hotspotObjectConstant.isInternedString(); 142 } 143 if (snippet == null) { 144 throw new GraalError("Unsupported constant type: " + constant); 145 } 146 147 Arguments args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage()); 148 args.add("constant", value); 149 150 SnippetTemplate template = template(args); 151 template.instantiate(providers.getMetaAccess(), resolveConstantNode, DEFAULT_REPLACER, tool, args); 152 153 assert resolveConstantNode.hasNoUsages(); 154 if (!resolveConstantNode.isDeleted()) { 155 GraphUtil.killWithUnusedFloatingInputs(resolveConstantNode); 156 } 157 } 158 159 public void lower(InitializeKlassNode initializeKlassNode, LoweringTool tool) { 160 StructuredGraph graph = initializeKlassNode.graph(); 161 162 ValueNode value = initializeKlassNode.value(); 163 assert value.isConstant() : "Expected a constant: " + value; 164 Constant constant = value.asConstant(); 165 166 if (constant instanceof HotSpotMetaspaceConstant) { 167 Arguments args = new Arguments(initializeKlass, graph.getGuardsStage(), tool.getLoweringStage()); 168 args.add("constant", value); 169 170 SnippetTemplate template = template(args); 171 template.instantiate(providers.getMetaAccess(), initializeKlassNode, DEFAULT_REPLACER, args); 172 assert initializeKlassNode.hasNoUsages(); 173 if (!initializeKlassNode.isDeleted()) { 174 GraphUtil.killWithUnusedFloatingInputs(initializeKlassNode); 175 } 176 177 } else { 178 throw new GraalError("Unsupported constant type: " + constant); 179 } 180 } 181 182 public void lower(ResolveMethodAndLoadCountersNode resolveMethodAndLoadCountersNode, LoweringTool tool) { 183 StructuredGraph graph = resolveMethodAndLoadCountersNode.graph(); 184 ConstantNode method = ConstantNode.forConstant(MethodPointerStamp.methodNonNull(), resolveMethodAndLoadCountersNode.getMethod().getEncoding(), tool.getMetaAccess(), graph); 185 Arguments args = new Arguments(resolveMethodAndLoadCounters, graph.getGuardsStage(), tool.getLoweringStage()); 186 args.add("method", method); 187 args.add("klassHint", resolveMethodAndLoadCountersNode.getHub()); 188 SnippetTemplate template = template(args); 189 template.instantiate(providers.getMetaAccess(), resolveMethodAndLoadCountersNode, DEFAULT_REPLACER, tool, args); 190 191 assert resolveMethodAndLoadCountersNode.hasNoUsages(); 192 if (!resolveMethodAndLoadCountersNode.isDeleted()) { 193 GraphUtil.killWithUnusedFloatingInputs(resolveMethodAndLoadCountersNode); 194 } 195 } 196 } 197 }