1 /* 2 * Copyright (c) 2015, 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 24 25 package org.graalvm.compiler.hotspot.meta; 26 27 import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; 28 29 import org.graalvm.compiler.core.common.type.StampPair; 30 import org.graalvm.compiler.nodes.ConstantNode; 31 import org.graalvm.compiler.nodes.ValueNode; 32 import org.graalvm.compiler.nodes.extended.GuardingNode; 33 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; 34 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderTool; 35 import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin; 36 import org.graalvm.compiler.nodes.graphbuilderconf.NodePlugin; 37 import org.graalvm.compiler.nodes.graphbuilderconf.TypePlugin; 38 import org.graalvm.compiler.nodes.util.ConstantFoldUtil; 39 import org.graalvm.compiler.word.Word; 40 import org.graalvm.compiler.word.WordOperationPlugin; 41 42 import jdk.vm.ci.meta.JavaConstant; 43 import jdk.vm.ci.meta.JavaKind; 44 import jdk.vm.ci.meta.JavaType; 45 import jdk.vm.ci.meta.JavaTypeProfile; 46 import jdk.vm.ci.meta.ResolvedJavaField; 47 import jdk.vm.ci.meta.ResolvedJavaMethod; 48 import jdk.vm.ci.meta.ResolvedJavaType; 49 50 /** 51 * This plugin handles the HotSpot-specific customizations of bytecode parsing: 52 * <p> 53 * {@link Word}-type rewriting for {@link GraphBuilderContext#parsingIntrinsic intrinsic} functions 54 * (snippets and method substitutions), by forwarding to the {@link WordOperationPlugin}. Note that 55 * we forward the {@link NodePlugin} and {@link TypePlugin} methods, but not the 56 * {@link InlineInvokePlugin} methods implemented by {@link WordOperationPlugin}. The latter is not 57 * necessary because HotSpot only uses the {@link Word} type in methods that are force-inlined, 58 * i.e., there are never non-inlined invokes that involve the {@link Word} type. 59 * <p> 60 * Constant folding of field loads. 61 */ 62 public final class HotSpotNodePlugin implements NodePlugin, TypePlugin { 63 protected final WordOperationPlugin wordOperationPlugin; 64 HotSpotNodePlugin(WordOperationPlugin wordOperationPlugin)65 public HotSpotNodePlugin(WordOperationPlugin wordOperationPlugin) { 66 this.wordOperationPlugin = wordOperationPlugin; 67 } 68 69 @Override canChangeStackKind(GraphBuilderContext b)70 public boolean canChangeStackKind(GraphBuilderContext b) { 71 if (b.parsingIntrinsic()) { 72 return wordOperationPlugin.canChangeStackKind(b); 73 } 74 return false; 75 } 76 77 @Override interceptType(GraphBuilderTool b, JavaType declaredType, boolean nonNull)78 public StampPair interceptType(GraphBuilderTool b, JavaType declaredType, boolean nonNull) { 79 if (b.parsingIntrinsic()) { 80 return wordOperationPlugin.interceptType(b, declaredType, nonNull); 81 } 82 return null; 83 } 84 85 @Override handleInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args)86 public boolean handleInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) { 87 if (b.parsingIntrinsic() && wordOperationPlugin.handleInvoke(b, method, args)) { 88 return true; 89 } 90 return false; 91 } 92 93 @Override handleLoadField(GraphBuilderContext b, ValueNode object, ResolvedJavaField field)94 public boolean handleLoadField(GraphBuilderContext b, ValueNode object, ResolvedJavaField field) { 95 if (!ImmutableCode.getValue(b.getOptions()) || b.parsingIntrinsic()) { 96 if (object.isConstant()) { 97 JavaConstant asJavaConstant = object.asJavaConstant(); 98 if (tryReadField(b, field, asJavaConstant)) { 99 return true; 100 } 101 } 102 } 103 if (b.parsingIntrinsic() && wordOperationPlugin.handleLoadField(b, object, field)) { 104 return true; 105 } 106 return false; 107 } 108 109 @Override handleLoadStaticField(GraphBuilderContext b, ResolvedJavaField field)110 public boolean handleLoadStaticField(GraphBuilderContext b, ResolvedJavaField field) { 111 if (!ImmutableCode.getValue(b.getOptions()) || b.parsingIntrinsic()) { 112 if (tryReadField(b, field, null)) { 113 return true; 114 } 115 } 116 if (b.parsingIntrinsic() && wordOperationPlugin.handleLoadStaticField(b, field)) { 117 return true; 118 } 119 return false; 120 } 121 tryReadField(GraphBuilderContext b, ResolvedJavaField field, JavaConstant object)122 private static boolean tryReadField(GraphBuilderContext b, ResolvedJavaField field, JavaConstant object) { 123 return tryConstantFold(b, field, object); 124 } 125 tryConstantFold(GraphBuilderContext b, ResolvedJavaField field, JavaConstant object)126 private static boolean tryConstantFold(GraphBuilderContext b, ResolvedJavaField field, JavaConstant object) { 127 ConstantNode result = ConstantFoldUtil.tryConstantFold(b.getConstantFieldProvider(), b.getConstantReflection(), b.getMetaAccess(), field, object, b.getOptions()); 128 if (result != null) { 129 result = b.getGraph().unique(result); 130 b.push(field.getJavaKind(), result); 131 return true; 132 } 133 return false; 134 } 135 136 @Override handleStoreField(GraphBuilderContext b, ValueNode object, ResolvedJavaField field, ValueNode value)137 public boolean handleStoreField(GraphBuilderContext b, ValueNode object, ResolvedJavaField field, ValueNode value) { 138 if (b.parsingIntrinsic() && wordOperationPlugin.handleStoreField(b, object, field, value)) { 139 return true; 140 } 141 return false; 142 } 143 144 @Override handleStoreStaticField(GraphBuilderContext b, ResolvedJavaField field, ValueNode value)145 public boolean handleStoreStaticField(GraphBuilderContext b, ResolvedJavaField field, ValueNode value) { 146 if (b.parsingIntrinsic() && wordOperationPlugin.handleStoreStaticField(b, field, value)) { 147 return true; 148 } 149 return false; 150 } 151 152 @Override handleLoadIndexed(GraphBuilderContext b, ValueNode array, ValueNode index, GuardingNode boundsCheck, JavaKind elementKind)153 public boolean handleLoadIndexed(GraphBuilderContext b, ValueNode array, ValueNode index, GuardingNode boundsCheck, JavaKind elementKind) { 154 if (b.parsingIntrinsic() && wordOperationPlugin.handleLoadIndexed(b, array, index, boundsCheck, elementKind)) { 155 return true; 156 } 157 return false; 158 } 159 160 @Override handleStoreIndexed(GraphBuilderContext b, ValueNode array, ValueNode index, GuardingNode boundsCheck, GuardingNode storeCheck, JavaKind elementKind, ValueNode value)161 public boolean handleStoreIndexed(GraphBuilderContext b, ValueNode array, ValueNode index, GuardingNode boundsCheck, GuardingNode storeCheck, JavaKind elementKind, ValueNode value) { 162 if (b.parsingIntrinsic() && wordOperationPlugin.handleStoreIndexed(b, array, index, boundsCheck, storeCheck, elementKind, value)) { 163 return true; 164 } 165 return false; 166 } 167 168 @Override handleCheckCast(GraphBuilderContext b, ValueNode object, ResolvedJavaType type, JavaTypeProfile profile)169 public boolean handleCheckCast(GraphBuilderContext b, ValueNode object, ResolvedJavaType type, JavaTypeProfile profile) { 170 if (b.parsingIntrinsic() && wordOperationPlugin.handleCheckCast(b, object, type, profile)) { 171 return true; 172 } 173 return false; 174 } 175 176 @Override handleInstanceOf(GraphBuilderContext b, ValueNode object, ResolvedJavaType type, JavaTypeProfile profile)177 public boolean handleInstanceOf(GraphBuilderContext b, ValueNode object, ResolvedJavaType type, JavaTypeProfile profile) { 178 if (b.parsingIntrinsic() && wordOperationPlugin.handleInstanceOf(b, object, type, profile)) { 179 return true; 180 } 181 return false; 182 } 183 } 184