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