1/* 2 * Copyright (c) 2011, 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.nodes.graphbuilderconf; 24 25import java.util.Arrays; 26 27import org.graalvm.compiler.core.common.GraalOptions; 28import org.graalvm.compiler.core.common.type.StampPair; 29 30import jdk.vm.ci.meta.JavaType; 31import jdk.vm.ci.meta.ResolvedJavaType; 32 33public class GraphBuilderConfiguration { 34 35 public static class Plugins { 36 private final InvocationPlugins invocationPlugins; 37 private NodePlugin[] nodePlugins; 38 private ParameterPlugin[] parameterPlugins; 39 private TypePlugin[] typePlugins; 40 private InlineInvokePlugin[] inlineInvokePlugins; 41 private LoopExplosionPlugin loopExplosionPlugin; 42 private ClassInitializationPlugin classInitializationPlugin; 43 private ProfilingPlugin profilingPlugin; 44 45 /** 46 * Creates a copy of a given set of plugins. The {@link InvocationPlugins} in 47 * {@code copyFrom} become the {@linkplain InvocationPlugins#getParent() default} 48 * {@linkplain #getInvocationPlugins() invocation plugins} in this object. 49 */ 50 public Plugins(Plugins copyFrom) { 51 this.invocationPlugins = new InvocationPlugins(copyFrom.invocationPlugins); 52 this.nodePlugins = copyFrom.nodePlugins; 53 this.parameterPlugins = copyFrom.parameterPlugins; 54 this.typePlugins = copyFrom.typePlugins; 55 this.inlineInvokePlugins = copyFrom.inlineInvokePlugins; 56 this.loopExplosionPlugin = copyFrom.loopExplosionPlugin; 57 this.classInitializationPlugin = copyFrom.classInitializationPlugin; 58 this.profilingPlugin = copyFrom.profilingPlugin; 59 } 60 61 /** 62 * Creates a new set of plugins. 63 * 64 * @param invocationPlugins the {@linkplain #getInvocationPlugins() invocation plugins} in 65 * this object 66 */ 67 public Plugins(InvocationPlugins invocationPlugins) { 68 this.invocationPlugins = invocationPlugins; 69 this.nodePlugins = new NodePlugin[0]; 70 this.parameterPlugins = new ParameterPlugin[0]; 71 this.typePlugins = new TypePlugin[0]; 72 this.inlineInvokePlugins = new InlineInvokePlugin[0]; 73 } 74 75 public InvocationPlugins getInvocationPlugins() { 76 return invocationPlugins; 77 } 78 79 public NodePlugin[] getNodePlugins() { 80 return nodePlugins; 81 } 82 83 public void appendNodePlugin(NodePlugin plugin) { 84 nodePlugins = Arrays.copyOf(nodePlugins, nodePlugins.length + 1); 85 nodePlugins[nodePlugins.length - 1] = plugin; 86 } 87 88 public void prependNodePlugin(NodePlugin plugin) { 89 NodePlugin[] newPlugins = new NodePlugin[nodePlugins.length + 1]; 90 System.arraycopy(nodePlugins, 0, newPlugins, 1, nodePlugins.length); 91 newPlugins[0] = plugin; 92 nodePlugins = newPlugins; 93 } 94 95 public void clearNodePlugin() { 96 nodePlugins = new NodePlugin[0]; 97 } 98 99 public ParameterPlugin[] getParameterPlugins() { 100 return parameterPlugins; 101 } 102 103 public void appendParameterPlugin(ParameterPlugin plugin) { 104 parameterPlugins = Arrays.copyOf(parameterPlugins, parameterPlugins.length + 1); 105 parameterPlugins[parameterPlugins.length - 1] = plugin; 106 } 107 108 public void prependParameterPlugin(ParameterPlugin plugin) { 109 ParameterPlugin[] newPlugins = new ParameterPlugin[parameterPlugins.length + 1]; 110 System.arraycopy(parameterPlugins, 0, newPlugins, 1, parameterPlugins.length); 111 newPlugins[0] = plugin; 112 parameterPlugins = newPlugins; 113 } 114 115 public TypePlugin[] getTypePlugins() { 116 return typePlugins; 117 } 118 119 public void appendTypePlugin(TypePlugin plugin) { 120 typePlugins = Arrays.copyOf(typePlugins, typePlugins.length + 1); 121 typePlugins[typePlugins.length - 1] = plugin; 122 } 123 124 public void prependTypePlugin(TypePlugin plugin) { 125 TypePlugin[] newPlugins = new TypePlugin[typePlugins.length + 1]; 126 System.arraycopy(typePlugins, 0, newPlugins, 1, typePlugins.length); 127 newPlugins[0] = plugin; 128 typePlugins = newPlugins; 129 } 130 131 public void clearParameterPlugin() { 132 parameterPlugins = new ParameterPlugin[0]; 133 } 134 135 public InlineInvokePlugin[] getInlineInvokePlugins() { 136 return inlineInvokePlugins; 137 } 138 139 public void appendInlineInvokePlugin(InlineInvokePlugin plugin) { 140 inlineInvokePlugins = Arrays.copyOf(inlineInvokePlugins, inlineInvokePlugins.length + 1); 141 inlineInvokePlugins[inlineInvokePlugins.length - 1] = plugin; 142 } 143 144 public void prependInlineInvokePlugin(InlineInvokePlugin plugin) { 145 InlineInvokePlugin[] newPlugins = new InlineInvokePlugin[inlineInvokePlugins.length + 1]; 146 System.arraycopy(inlineInvokePlugins, 0, newPlugins, 1, inlineInvokePlugins.length); 147 newPlugins[0] = plugin; 148 inlineInvokePlugins = newPlugins; 149 } 150 151 public void clearInlineInvokePlugins() { 152 inlineInvokePlugins = new InlineInvokePlugin[0]; 153 } 154 155 public LoopExplosionPlugin getLoopExplosionPlugin() { 156 return loopExplosionPlugin; 157 } 158 159 public void setLoopExplosionPlugin(LoopExplosionPlugin plugin) { 160 this.loopExplosionPlugin = plugin; 161 } 162 163 public ClassInitializationPlugin getClassInitializationPlugin() { 164 return classInitializationPlugin; 165 } 166 167 public void setClassInitializationPlugin(ClassInitializationPlugin plugin) { 168 this.classInitializationPlugin = plugin; 169 } 170 171 public ProfilingPlugin getProfilingPlugin() { 172 return profilingPlugin; 173 } 174 175 public void setProfilingPlugin(ProfilingPlugin plugin) { 176 this.profilingPlugin = plugin; 177 } 178 179 public StampPair getOverridingStamp(GraphBuilderTool b, JavaType type, boolean nonNull) { 180 for (TypePlugin plugin : getTypePlugins()) { 181 StampPair stamp = plugin.interceptType(b, type, nonNull); 182 if (stamp != null) { 183 return stamp; 184 } 185 } 186 return null; 187 } 188 } 189 190 private static final ResolvedJavaType[] EMPTY = new ResolvedJavaType[]{}; 191 192 private final boolean eagerResolving; 193 private final BytecodeExceptionMode bytecodeExceptionMode; 194 private final boolean omitAssertions; 195 private final ResolvedJavaType[] skippedExceptionTypes; 196 private final boolean insertFullInfopoints; 197 private final boolean trackNodeSourcePosition; 198 private final boolean clearNonLiveLocals; 199 private final Plugins plugins; 200 201 public enum BytecodeExceptionMode { 202 /** 203 * This mode always explicitly checks for exceptions. 204 */ 205 CheckAll, 206 /** 207 * This mode omits all explicit exception edges. 208 */ 209 OmitAll, 210 /** 211 * This mode uses profiling information to decide whether to use explicit exception edges. 212 */ 213 Profile 214 } 215 216 protected GraphBuilderConfiguration(boolean eagerResolving, BytecodeExceptionMode bytecodeExceptionMode, boolean omitAssertions, boolean insertFullInfopoints, 217 boolean trackNodeSourcePosition, ResolvedJavaType[] skippedExceptionTypes, 218 boolean clearNonLiveLocals, Plugins plugins) { 219 this.eagerResolving = eagerResolving; 220 this.bytecodeExceptionMode = bytecodeExceptionMode; 221 this.omitAssertions = omitAssertions; 222 this.insertFullInfopoints = insertFullInfopoints; 223 this.trackNodeSourcePosition = trackNodeSourcePosition; 224 this.skippedExceptionTypes = skippedExceptionTypes; 225 this.clearNonLiveLocals = clearNonLiveLocals; 226 this.plugins = plugins; 227 } 228 229 /** 230 * Creates a copy of this configuration with all its plugins. The {@link InvocationPlugins} in 231 * this configuration become the {@linkplain InvocationPlugins#getParent() parent} of the 232 * {@link InvocationPlugins} in the copy. 233 */ 234 public GraphBuilderConfiguration copy() { 235 Plugins newPlugins = new Plugins(plugins); 236 GraphBuilderConfiguration result = new GraphBuilderConfiguration(eagerResolving, bytecodeExceptionMode, omitAssertions, insertFullInfopoints, trackNodeSourcePosition, skippedExceptionTypes, 237 clearNonLiveLocals, newPlugins); 238 return result; 239 } 240 241 public GraphBuilderConfiguration withEagerResolving(boolean newEagerResolving) { 242 return new GraphBuilderConfiguration(newEagerResolving, bytecodeExceptionMode, omitAssertions, insertFullInfopoints, trackNodeSourcePosition, skippedExceptionTypes, clearNonLiveLocals, 243 plugins); 244 } 245 246 public GraphBuilderConfiguration withSkippedExceptionTypes(ResolvedJavaType[] newSkippedExceptionTypes) { 247 return new GraphBuilderConfiguration(eagerResolving, bytecodeExceptionMode, omitAssertions, insertFullInfopoints, trackNodeSourcePosition, newSkippedExceptionTypes, clearNonLiveLocals, 248 plugins); 249 } 250 251 public GraphBuilderConfiguration withBytecodeExceptionMode(BytecodeExceptionMode newBytecodeExceptionMode) { 252 return new GraphBuilderConfiguration(eagerResolving, newBytecodeExceptionMode, omitAssertions, insertFullInfopoints, trackNodeSourcePosition, skippedExceptionTypes, clearNonLiveLocals, 253 plugins); 254 } 255 256 public GraphBuilderConfiguration withOmitAssertions(boolean newOmitAssertions) { 257 return new GraphBuilderConfiguration(eagerResolving, bytecodeExceptionMode, newOmitAssertions, insertFullInfopoints, trackNodeSourcePosition, skippedExceptionTypes, clearNonLiveLocals, 258 plugins); 259 } 260 261 public GraphBuilderConfiguration withFullInfopoints(boolean newInsertFullInfopoints) { 262 ResolvedJavaType[] newSkippedExceptionTypes = skippedExceptionTypes == EMPTY ? EMPTY : Arrays.copyOf(skippedExceptionTypes, skippedExceptionTypes.length); 263 return new GraphBuilderConfiguration(eagerResolving, bytecodeExceptionMode, omitAssertions, newInsertFullInfopoints, trackNodeSourcePosition, newSkippedExceptionTypes, clearNonLiveLocals, 264 plugins); 265 } 266 267 public GraphBuilderConfiguration withNodeSourcePosition(boolean newTrackNodeSourcePosition) { 268 ResolvedJavaType[] newSkippedExceptionTypes = skippedExceptionTypes == EMPTY ? EMPTY : Arrays.copyOf(skippedExceptionTypes, skippedExceptionTypes.length); 269 return new GraphBuilderConfiguration(eagerResolving, bytecodeExceptionMode, omitAssertions, insertFullInfopoints, newTrackNodeSourcePosition, newSkippedExceptionTypes, clearNonLiveLocals, 270 plugins); 271 } 272 273 public GraphBuilderConfiguration withClearNonLiveLocals(boolean newClearNonLiveLocals) { 274 return new GraphBuilderConfiguration(eagerResolving, bytecodeExceptionMode, omitAssertions, insertFullInfopoints, trackNodeSourcePosition, skippedExceptionTypes, newClearNonLiveLocals, 275 plugins); 276 } 277 278 public ResolvedJavaType[] getSkippedExceptionTypes() { 279 return skippedExceptionTypes; 280 } 281 282 public boolean eagerResolving() { 283 return eagerResolving; 284 } 285 286 public BytecodeExceptionMode getBytecodeExceptionMode() { 287 return bytecodeExceptionMode; 288 } 289 290 public boolean omitAssertions() { 291 return omitAssertions; 292 } 293 294 public boolean trackNodeSourcePosition() { 295 return trackNodeSourcePosition; 296 } 297 298 public boolean insertFullInfopoints() { 299 return insertFullInfopoints; 300 } 301 302 public boolean clearNonLiveLocals() { 303 return clearNonLiveLocals; 304 } 305 306 public static GraphBuilderConfiguration getDefault(Plugins plugins) { 307 return new GraphBuilderConfiguration(false, BytecodeExceptionMode.Profile, false, false, false, EMPTY, GraalOptions.OptClearNonLiveLocals.getValue(), plugins); 308 } 309 310 public static GraphBuilderConfiguration getSnippetDefault(Plugins plugins) { 311 return new GraphBuilderConfiguration(true, BytecodeExceptionMode.OmitAll, false, false, false, EMPTY, GraalOptions.OptClearNonLiveLocals.getValue(), plugins); 312 } 313 314 /** 315 * Returns {@code true} if it is an error for a class/field/method resolution to fail. The 316 * default is the same result as returned by {@link #eagerResolving()}. However, it may be 317 * overridden to allow failure even when {@link #eagerResolving} is {@code true}. 318 */ 319 public boolean unresolvedIsError() { 320 return eagerResolving; 321 } 322 323 public Plugins getPlugins() { 324 return plugins; 325 } 326} 327