1 /* 2 * Copyright (c) 2011, 2018, 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.nodes.graphbuilderconf; 26 27 import java.util.Arrays; 28 import java.util.Collections; 29 import java.util.List; 30 31 import org.graalvm.compiler.core.common.type.StampPair; 32 33 import jdk.vm.ci.meta.JavaType; 34 import jdk.vm.ci.meta.ResolvedJavaType; 35 36 public final class GraphBuilderConfiguration { 37 38 public static class Plugins { 39 private final InvocationPlugins invocationPlugins; 40 private NodePlugin[] nodePlugins; 41 private ParameterPlugin[] parameterPlugins; 42 private TypePlugin[] typePlugins; 43 private InlineInvokePlugin[] inlineInvokePlugins; 44 private ClassInitializationPlugin classInitializationPlugin; 45 private InvokeDynamicPlugin invokeDynamicPlugin; 46 private ProfilingPlugin profilingPlugin; 47 48 /** 49 * Creates a copy of a given set of plugins. The {@link InvocationPlugins} in 50 * {@code copyFrom} become the {@linkplain InvocationPlugins#getParent() default} 51 * {@linkplain #getInvocationPlugins() invocation plugins} in this object. 52 */ 53 public Plugins(Plugins copyFrom, InvocationPlugins invocationPlugins) { 54 this.invocationPlugins = invocationPlugins != null ? invocationPlugins : new InvocationPlugins(copyFrom.invocationPlugins); 55 this.nodePlugins = copyFrom.nodePlugins; 56 this.parameterPlugins = copyFrom.parameterPlugins; 57 this.typePlugins = copyFrom.typePlugins; 58 this.inlineInvokePlugins = copyFrom.inlineInvokePlugins; 59 this.classInitializationPlugin = copyFrom.classInitializationPlugin; 60 this.invokeDynamicPlugin = copyFrom.invokeDynamicPlugin; 61 this.profilingPlugin = copyFrom.profilingPlugin; 62 } 63 64 public Plugins(Plugins copyFrom) { 65 this(copyFrom, null); 66 } 67 68 /** 69 * Creates a new set of plugins. 70 * 71 * @param invocationPlugins the {@linkplain #getInvocationPlugins() invocation plugins} in 72 * this object 73 */ 74 public Plugins(InvocationPlugins invocationPlugins) { 75 this.invocationPlugins = invocationPlugins; 76 this.nodePlugins = new NodePlugin[0]; 77 this.parameterPlugins = new ParameterPlugin[0]; 78 this.typePlugins = new TypePlugin[0]; 79 this.inlineInvokePlugins = new InlineInvokePlugin[0]; 80 } 81 82 public InvocationPlugins getInvocationPlugins() { 83 return invocationPlugins; 84 } 85 86 public NodePlugin[] getNodePlugins() { 87 return nodePlugins; 88 } 89 90 public void appendNodePlugin(NodePlugin plugin) { 91 nodePlugins = Arrays.copyOf(nodePlugins, nodePlugins.length + 1); 92 nodePlugins[nodePlugins.length - 1] = plugin; 93 } 94 95 public void prependNodePlugin(NodePlugin plugin) { 96 NodePlugin[] newPlugins = new NodePlugin[nodePlugins.length + 1]; 97 System.arraycopy(nodePlugins, 0, newPlugins, 1, nodePlugins.length); 98 newPlugins[0] = plugin; 99 nodePlugins = newPlugins; 100 } 101 102 public void clearNodePlugin() { 103 nodePlugins = new NodePlugin[0]; 104 } 105 106 public ParameterPlugin[] getParameterPlugins() { 107 return parameterPlugins; 108 } 109 110 public void appendParameterPlugin(ParameterPlugin plugin) { 111 parameterPlugins = Arrays.copyOf(parameterPlugins, parameterPlugins.length + 1); 112 parameterPlugins[parameterPlugins.length - 1] = plugin; 113 } 114 115 public void prependParameterPlugin(ParameterPlugin plugin) { 116 ParameterPlugin[] newPlugins = new ParameterPlugin[parameterPlugins.length + 1]; 117 System.arraycopy(parameterPlugins, 0, newPlugins, 1, parameterPlugins.length); 118 newPlugins[0] = plugin; 119 parameterPlugins = newPlugins; 120 } 121 122 public TypePlugin[] getTypePlugins() { 123 return typePlugins; 124 } 125 126 public void appendTypePlugin(TypePlugin plugin) { 127 typePlugins = Arrays.copyOf(typePlugins, typePlugins.length + 1); 128 typePlugins[typePlugins.length - 1] = plugin; 129 } 130 131 public void prependTypePlugin(TypePlugin plugin) { 132 TypePlugin[] newPlugins = new TypePlugin[typePlugins.length + 1]; 133 System.arraycopy(typePlugins, 0, newPlugins, 1, typePlugins.length); 134 newPlugins[0] = plugin; 135 typePlugins = newPlugins; 136 } 137 138 public void clearParameterPlugin() { 139 parameterPlugins = new ParameterPlugin[0]; 140 } 141 142 public InlineInvokePlugin[] getInlineInvokePlugins() { 143 return inlineInvokePlugins; 144 } 145 146 public void appendInlineInvokePlugin(InlineInvokePlugin plugin) { 147 inlineInvokePlugins = Arrays.copyOf(inlineInvokePlugins, inlineInvokePlugins.length + 1); 148 inlineInvokePlugins[inlineInvokePlugins.length - 1] = plugin; 149 } 150 151 public void prependInlineInvokePlugin(InlineInvokePlugin plugin) { 152 InlineInvokePlugin[] newPlugins = new InlineInvokePlugin[inlineInvokePlugins.length + 1]; 153 System.arraycopy(inlineInvokePlugins, 0, newPlugins, 1, inlineInvokePlugins.length); 154 newPlugins[0] = plugin; 155 inlineInvokePlugins = newPlugins; 156 } 157 158 public void clearInlineInvokePlugins() { 159 inlineInvokePlugins = new InlineInvokePlugin[0]; 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 InvokeDynamicPlugin getInvokeDynamicPlugin() { 171 return invokeDynamicPlugin; 172 } 173 174 public void setInvokeDynamicPlugin(InvokeDynamicPlugin plugin) { 175 this.invokeDynamicPlugin = plugin; 176 } 177 178 public ProfilingPlugin getProfilingPlugin() { 179 return profilingPlugin; 180 } 181 182 public void setProfilingPlugin(ProfilingPlugin plugin) { 183 this.profilingPlugin = plugin; 184 } 185 186 public StampPair getOverridingStamp(GraphBuilderTool b, JavaType type, boolean nonNull) { 187 for (TypePlugin plugin : getTypePlugins()) { 188 StampPair stamp = plugin.interceptType(b, type, nonNull); 189 if (stamp != null) { 190 return stamp; 191 } 192 } 193 return null; 194 } 195 } 196 197 private final boolean eagerResolving; 198 private final boolean unresolvedIsError; 199 private final BytecodeExceptionMode bytecodeExceptionMode; 200 private final boolean omitAssertions; 201 private final List<ResolvedJavaType> skippedExceptionTypes; 202 private final boolean insertFullInfopoints; 203 private final boolean trackNodeSourcePosition; 204 private final boolean retainLocalVariables; 205 private final Plugins plugins; 206 207 public enum BytecodeExceptionMode { 208 /** 209 * This mode always explicitly checks for exceptions. 210 */ 211 CheckAll, 212 /** 213 * This mode omits all explicit exception edges. 214 */ 215 OmitAll, 216 /** 217 * This mode omits exception edges at invokes, but not for implicit null checks or bounds 218 * checks. 219 */ 220 ExplicitOnly, 221 /** 222 * This mode uses profiling information to decide whether to use explicit exception edges. 223 */ 224 Profile 225 } 226 227 private GraphBuilderConfiguration(boolean eagerResolving, 228 boolean unresolvedIsError, 229 BytecodeExceptionMode bytecodeExceptionMode, 230 boolean omitAssertions, 231 boolean insertFullInfopoints, 232 boolean trackNodeSourcePosition, 233 boolean retainLocalVariables, 234 List<ResolvedJavaType> skippedExceptionTypes, 235 Plugins plugins) { 236 this.eagerResolving = eagerResolving; 237 this.unresolvedIsError = unresolvedIsError; 238 this.bytecodeExceptionMode = bytecodeExceptionMode; 239 this.omitAssertions = omitAssertions; 240 this.insertFullInfopoints = insertFullInfopoints; 241 this.trackNodeSourcePosition = trackNodeSourcePosition; 242 this.retainLocalVariables = retainLocalVariables; 243 this.skippedExceptionTypes = skippedExceptionTypes; 244 this.plugins = plugins; 245 } 246 247 /** 248 * Creates a copy of this configuration with all its plugins. The {@link InvocationPlugins} in 249 * this configuration become the {@linkplain InvocationPlugins#getParent() parent} of the 250 * {@link InvocationPlugins} in the copy. 251 */ 252 public GraphBuilderConfiguration copy() { 253 Plugins newPlugins = new Plugins(plugins); 254 GraphBuilderConfiguration result = new GraphBuilderConfiguration( 255 eagerResolving, 256 unresolvedIsError, 257 bytecodeExceptionMode, 258 omitAssertions, 259 insertFullInfopoints, 260 trackNodeSourcePosition, 261 retainLocalVariables, 262 skippedExceptionTypes, 263 newPlugins); 264 return result; 265 } 266 267 /** 268 * Set the {@link #unresolvedIsError} flag. This flag can be set independently from 269 * {@link #eagerResolving}, i.e., even if eager resolving fails execution is assumed to be 270 * valid. This allows us for example to process unresolved types/methods/fields even when 271 * eagerly resolving elements. 272 */ 273 public GraphBuilderConfiguration withUnresolvedIsError(boolean newUnresolvedIsError) { 274 return new GraphBuilderConfiguration( 275 eagerResolving, 276 newUnresolvedIsError, 277 bytecodeExceptionMode, 278 omitAssertions, 279 insertFullInfopoints, 280 trackNodeSourcePosition, 281 retainLocalVariables, 282 skippedExceptionTypes, 283 plugins); 284 } 285 286 public GraphBuilderConfiguration withEagerResolving(boolean newEagerResolving) { 287 return new GraphBuilderConfiguration( 288 newEagerResolving, 289 unresolvedIsError, 290 bytecodeExceptionMode, 291 omitAssertions, 292 insertFullInfopoints, 293 trackNodeSourcePosition, 294 retainLocalVariables, 295 skippedExceptionTypes, 296 plugins); 297 } 298 299 public GraphBuilderConfiguration withSkippedExceptionTypes(ResolvedJavaType[] newSkippedExceptionTypes) { 300 return new GraphBuilderConfiguration( 301 eagerResolving, 302 unresolvedIsError, 303 bytecodeExceptionMode, 304 omitAssertions, 305 insertFullInfopoints, 306 trackNodeSourcePosition, 307 retainLocalVariables, 308 Collections.unmodifiableList(Arrays.asList(newSkippedExceptionTypes)), 309 plugins); 310 } 311 312 public GraphBuilderConfiguration withBytecodeExceptionMode(BytecodeExceptionMode newBytecodeExceptionMode) { 313 return new GraphBuilderConfiguration(eagerResolving, 314 unresolvedIsError, 315 newBytecodeExceptionMode, 316 omitAssertions, 317 insertFullInfopoints, 318 trackNodeSourcePosition, 319 retainLocalVariables, 320 skippedExceptionTypes, 321 plugins); 322 } 323 324 public GraphBuilderConfiguration withOmitAssertions(boolean newOmitAssertions) { 325 return new GraphBuilderConfiguration( 326 eagerResolving, 327 unresolvedIsError, 328 bytecodeExceptionMode, 329 newOmitAssertions, 330 insertFullInfopoints, 331 trackNodeSourcePosition, 332 retainLocalVariables, 333 skippedExceptionTypes, 334 plugins); 335 } 336 337 public GraphBuilderConfiguration withFullInfopoints(boolean newInsertFullInfopoints) { 338 return new GraphBuilderConfiguration( 339 eagerResolving, 340 unresolvedIsError, 341 bytecodeExceptionMode, 342 omitAssertions, 343 newInsertFullInfopoints, 344 trackNodeSourcePosition, 345 retainLocalVariables, 346 skippedExceptionTypes, 347 plugins); 348 } 349 350 public GraphBuilderConfiguration withNodeSourcePosition(boolean newTrackNodeSourcePosition) { 351 return new GraphBuilderConfiguration( 352 eagerResolving, 353 unresolvedIsError, 354 bytecodeExceptionMode, 355 omitAssertions, 356 insertFullInfopoints, 357 newTrackNodeSourcePosition, 358 retainLocalVariables, 359 skippedExceptionTypes, 360 plugins); 361 } 362 363 public GraphBuilderConfiguration withRetainLocalVariables(boolean newRetainLocalVariables) { 364 return new GraphBuilderConfiguration( 365 eagerResolving, 366 unresolvedIsError, 367 bytecodeExceptionMode, 368 omitAssertions, 369 insertFullInfopoints, 370 trackNodeSourcePosition, 371 newRetainLocalVariables, 372 skippedExceptionTypes, 373 plugins); 374 } 375 376 public List<ResolvedJavaType> getSkippedExceptionTypes() { 377 return skippedExceptionTypes; 378 } 379 380 public boolean eagerResolving() { 381 return eagerResolving; 382 } 383 384 public BytecodeExceptionMode getBytecodeExceptionMode() { 385 return bytecodeExceptionMode; 386 } 387 388 public boolean omitAssertions() { 389 return omitAssertions; 390 } 391 392 public boolean trackNodeSourcePosition() { 393 return trackNodeSourcePosition; 394 } 395 396 public boolean retainLocalVariables() { 397 return retainLocalVariables; 398 } 399 400 public boolean insertFullInfopoints() { 401 return insertFullInfopoints; 402 } 403 404 public static GraphBuilderConfiguration getDefault(Plugins plugins) { 405 return new GraphBuilderConfiguration( 406 /* eagerResolving: */ false, 407 /* unresolvedIsError: */ false, 408 BytecodeExceptionMode.Profile, 409 /* omitAssertions: */ false, 410 /* insertFullInfopoints: */ false, 411 /* trackNodeSourcePosition: */ false, 412 /* retainLocalVariables */ false, 413 Collections.emptyList(), 414 plugins); 415 } 416 417 public static GraphBuilderConfiguration getSnippetDefault(Plugins plugins) { 418 return new GraphBuilderConfiguration( 419 /* eagerResolving: */ true, 420 /* unresolvedIsError: */ true, 421 BytecodeExceptionMode.OmitAll, 422 /* omitAssertions: */ false, 423 /* insertFullInfopoints: */ false, 424 /* trackNodeSourcePosition: */ false, 425 /* retainLocalVariables */ false, 426 Collections.emptyList(), 427 plugins); 428 } 429 430 /** Returns {@code true} if it is an error for a class/field/method resolution to fail. */ 431 public boolean unresolvedIsError() { 432 return unresolvedIsError; 433 } 434 435 public Plugins getPlugins() { 436 return plugins; 437 } 438 }