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