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