ReplaceConstantNodesPhase.java revision 12657:6ef01bd40ce2
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 */ 23package org.graalvm.compiler.hotspot.phases.aot; 24 25import static org.graalvm.compiler.hotspot.nodes.aot.LoadMethodCountersNode.getLoadMethodCountersNodes; 26import static org.graalvm.compiler.nodes.ConstantNode.getConstantNodes; 27 28import java.util.HashSet; 29 30import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; 31import jdk.vm.ci.hotspot.HotSpotObjectConstant; 32import jdk.vm.ci.hotspot.HotSpotResolvedJavaType; 33import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; 34import jdk.vm.ci.meta.Constant; 35import jdk.vm.ci.meta.ConstantReflectionProvider; 36import jdk.vm.ci.meta.ResolvedJavaType; 37 38import org.graalvm.compiler.core.common.type.ObjectStamp; 39import org.graalvm.compiler.core.common.type.Stamp; 40import org.graalvm.compiler.core.common.type.StampFactory; 41import org.graalvm.compiler.debug.GraalError; 42import org.graalvm.compiler.graph.Node; 43import org.graalvm.compiler.hotspot.FingerprintUtil; 44import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction; 45import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode; 46import org.graalvm.compiler.hotspot.nodes.aot.LoadConstantIndirectlyFixedNode; 47import org.graalvm.compiler.hotspot.nodes.aot.LoadConstantIndirectlyNode; 48import org.graalvm.compiler.hotspot.nodes.aot.LoadMethodCountersNode; 49import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode; 50import org.graalvm.compiler.hotspot.nodes.aot.ResolveMethodAndLoadCountersNode; 51import org.graalvm.compiler.nodes.ConstantNode; 52import org.graalvm.compiler.nodes.StructuredGraph; 53import org.graalvm.compiler.nodes.ValueNode; 54import org.graalvm.compiler.phases.BasePhase; 55import org.graalvm.compiler.phases.tiers.PhaseContext; 56 57public class ReplaceConstantNodesPhase extends BasePhase<PhaseContext> { 58 59 private static final HashSet<Class<?>> builtIns = new HashSet<>(); 60 61 static { 62 builtIns.add(Boolean.class); 63 64 Class<?> characterCacheClass = Character.class.getDeclaredClasses()[0]; 65 assert "java.lang.Character$CharacterCache".equals(characterCacheClass.getName()); 66 builtIns.add(characterCacheClass); 67 68 Class<?> byteCacheClass = Byte.class.getDeclaredClasses()[0]; 69 assert "java.lang.Byte$ByteCache".equals(byteCacheClass.getName()); 70 builtIns.add(byteCacheClass); 71 72 Class<?> shortCacheClass = Short.class.getDeclaredClasses()[0]; 73 assert "java.lang.Short$ShortCache".equals(shortCacheClass.getName()); 74 builtIns.add(shortCacheClass); 75 76 Class<?> integerCacheClass = Integer.class.getDeclaredClasses()[0]; 77 assert "java.lang.Integer$IntegerCache".equals(integerCacheClass.getName()); 78 builtIns.add(integerCacheClass); 79 80 Class<?> longCacheClass = Long.class.getDeclaredClasses()[0]; 81 assert "java.lang.Long$LongCache".equals(longCacheClass.getName()); 82 builtIns.add(longCacheClass); 83 } 84 85 private static boolean isReplacementNode(Node n) { 86 // @formatter:off 87 return n instanceof LoadConstantIndirectlyNode || 88 n instanceof LoadConstantIndirectlyFixedNode || 89 n instanceof ResolveConstantNode || 90 n instanceof InitializeKlassNode; 91 // @formatter:on 92 } 93 94 private static boolean checkForBadFingerprint(HotSpotResolvedJavaType type) { 95 if (type.isArray()) { 96 if (type.getElementalType().isPrimitive()) { 97 return false; 98 } 99 return FingerprintUtil.getFingerprint((HotSpotResolvedObjectType) (type.getElementalType())) == 0; 100 } 101 return FingerprintUtil.getFingerprint((HotSpotResolvedObjectType) type) == 0; 102 } 103 104 private static void handleHotSpotMetaspaceConstant(StructuredGraph graph, ConstantNode node) { 105 HotSpotMetaspaceConstant metaspaceConstant = (HotSpotMetaspaceConstant) node.asConstant(); 106 HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) metaspaceConstant.asResolvedJavaType(); 107 108 if (type != null) { 109 if (checkForBadFingerprint(type)) { 110 throw new GraalError("Type with bad fingerprint: " + type); 111 } 112 113 assert !metaspaceConstant.isCompressed() : "No support for replacing compressed metaspace constants"; 114 ResolvedJavaType topMethodHolder = graph.method().getDeclaringClass(); 115 ValueNode replacement; 116 117 if (type.isArray() && type.getComponentType().isPrimitive()) { 118 // Special case for primitive arrays. The AOT runtime pre-resolves them, so we may 119 // omit the resolution call. 120 replacement = new LoadConstantIndirectlyNode(node); 121 } else if (type.equals(topMethodHolder) || (type.isAssignableFrom(topMethodHolder) && !type.isInterface())) { 122 // If it's a supertype of or the same class that declares the top method, we are 123 // guaranteed to have it resolved already. If it's an interface, we just test for 124 // equality. 125 replacement = new LoadConstantIndirectlyNode(node); 126 } else if (builtIns.contains(type.mirror())) { 127 // Special case of klass constants that come from {@link BoxingSnippets}. 128 replacement = new ResolveConstantNode(node, HotSpotConstantLoadAction.INITIALIZE); 129 } else { 130 replacement = new ResolveConstantNode(node); 131 } 132 133 node.replaceAtUsages(graph.addOrUnique(replacement), n -> !isReplacementNode(n)); 134 } else { 135 throw new GraalError("Unsupported metaspace constant type: " + type); 136 } 137 } 138 139 private static void handleHotSpotObjectConstant(StructuredGraph graph, ConstantNode node) { 140 HotSpotObjectConstant constant = (HotSpotObjectConstant) node.asJavaConstant(); 141 HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) constant.getType(); 142 if (type.mirror().equals(String.class)) { 143 assert !constant.isCompressed() : "No support for replacing compressed oop constants"; 144 ValueNode replacement = graph.unique(new ResolveConstantNode(node)); 145 node.replaceAtUsages(replacement, n -> !(n instanceof ResolveConstantNode)); 146 } else { 147 throw new GraalError("Unsupported object constant type: " + type); 148 } 149 } 150 151 private static void handleLoadMethodCounters(StructuredGraph graph, LoadMethodCountersNode node, PhaseContext context) { 152 ResolvedJavaType type = node.getMethod().getDeclaringClass(); 153 Stamp hubStamp = context.getStampProvider().createHubStamp((ObjectStamp) StampFactory.objectNonNull()); 154 ConstantReflectionProvider constantReflection = context.getConstantReflection(); 155 ConstantNode klassHint = ConstantNode.forConstant(hubStamp, constantReflection.asObjectHub(type), context.getMetaAccess(), graph); 156 ValueNode replacement = graph.unique(new ResolveMethodAndLoadCountersNode(node.getMethod(), klassHint)); 157 node.replaceAtUsages(replacement, n -> !(n instanceof ResolveMethodAndLoadCountersNode)); 158 } 159 160 @Override 161 protected void run(StructuredGraph graph, PhaseContext context) { 162 // Replace LoadMethodCountersNode with ResolveMethodAndLoadCountersNode, expose klass 163 // constants. 164 for (LoadMethodCountersNode node : getLoadMethodCountersNodes(graph)) { 165 handleLoadMethodCounters(graph, node, context); 166 } 167 168 // Replace object and klass constants (including the ones added in the previous pass) with 169 // resolution nodes. 170 for (ConstantNode node : getConstantNodes(graph)) { 171 Constant constant = node.asConstant(); 172 if (constant instanceof HotSpotMetaspaceConstant) { 173 handleHotSpotMetaspaceConstant(graph, node); 174 } else if (constant instanceof HotSpotObjectConstant) { 175 handleHotSpotObjectConstant(graph, node); 176 } 177 } 178 } 179 180 @Override 181 public boolean checkContract() { 182 return false; 183 } 184 185} 186