/*
 * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.graalvm.compiler.nodes.extended;

import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_8;
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_8;

import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.core.common.type.TypeReference;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.NodeInputList;
import org.graalvm.compiler.graph.spi.Canonicalizable;
import org.graalvm.compiler.graph.spi.CanonicalizerTool;
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodeinfo.Verbosity;
import org.graalvm.compiler.nodes.FrameState;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.memory.AbstractMemoryCheckpoint;
import org.graalvm.compiler.nodes.memory.SingleMemoryKill;
import org.graalvm.compiler.nodes.spi.Lowerable;
import org.graalvm.word.LocationIdentity;

import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.MetaAccessProvider;

A node that represents an exception thrown implicitly by a Java bytecode. It can be lowered to either a foreign call or a pre-allocated exception object.
/** * A node that represents an exception thrown implicitly by a Java bytecode. It can be lowered to * either a {@linkplain ForeignCallDescriptor foreign} call or a pre-allocated exception object. */
// @formatter:off @NodeInfo(cycles = CYCLES_8, cyclesRationale = "Node will be lowered to a foreign call.", size = SIZE_8) // @formatter:on public final class BytecodeExceptionNode extends AbstractMemoryCheckpoint implements Lowerable, SingleMemoryKill, Canonicalizable { public enum BytecodeExceptionKind {
Represents a NullPointerException. No arguments are allowed.
/** * Represents a {@link NullPointerException}. No arguments are allowed. */
NULL_POINTER(0, NullPointerException.class),
Represents a ArrayIndexOutOfBoundsException. Two arguments are required:
  1. The array index that could not be accessed (type: int)
  2. The length of the array that was accessed (type: int)
/** * Represents a {@link ArrayIndexOutOfBoundsException}. Two arguments are required: * <ol> * <li>The array index that could not be accessed (type: int)</li> * <li>The length of the array that was accessed (type: int)</li> * </ol> */
OUT_OF_BOUNDS(2, ArrayIndexOutOfBoundsException.class),
Represents a ClassCastException. Two arguments are required:
  1. The object that could not be cast (type: java.lang.Object, non-null)
  2. The class that the object should have been casted to (type: java.lang.Class, non-null)
/** * Represents a {@link ClassCastException}. Two arguments are required: * <ol> * <li>The object that could not be cast (type: java.lang.Object, non-null)</li> * <li>The class that the object should have been casted to (type: java.lang.Class, * non-null)</li> * </ol> */
CLASS_CAST(2, ClassCastException.class),
Represents a ArrayStoreException. One arguments is required:
  1. The value that could not be stored (type: java.lang.Object, non-null)
/** * Represents a {@link ArrayStoreException}. One arguments is required: * <ol> * <li>The value that could not be stored (type: java.lang.Object, non-null)</li> * </ol> */
ARRAY_STORE(1, ArrayStoreException.class),
Represents a IllegalArgumentException with a fixed message. No additional arguments are allowed.
/** * Represents a {@link IllegalArgumentException} with a fixed message. No additional * arguments are allowed. */
ILLEGAL_ARGUMENT_EXCEPTION_NEGATIVE_LENGTH(0, IllegalArgumentException.class, "Negative length"),
Represents a IllegalArgumentException with a fixed message. No additional arguments are allowed.
/** * Represents a {@link IllegalArgumentException} with a fixed message. No additional * arguments are allowed. */
ILLEGAL_ARGUMENT_EXCEPTION_ARGUMENT_IS_NOT_AN_ARRAY(0, IllegalArgumentException.class, "Argument is not an array"),
Represents a ArithmeticException, with the exception message indicating a division by zero. No arguments are allowed.
/** * Represents a {@link ArithmeticException}, with the exception message indicating a * division by zero. No arguments are allowed. */
DIVISION_BY_ZERO(0, ArithmeticException.class),
Represents a ArithmeticException, with the exception message indicating an integer overflow. No arguments are allowed.
/** * Represents a {@link ArithmeticException}, with the exception message indicating an * integer overflow. No arguments are allowed. */
INTEGER_EXACT_OVERFLOW(0, ArithmeticException.class),
Represents a ArithmeticException, with the exception message indicating a long overflow. No arguments are allowed.
/** * Represents a {@link ArithmeticException}, with the exception message indicating a long * overflow. No arguments are allowed. */
LONG_EXACT_OVERFLOW(0, ArithmeticException.class); final int numArguments; final Class<? extends Throwable> exceptionClass; final String exceptionMessage; BytecodeExceptionKind(int numArguments, Class<? extends Throwable> exceptionClass) { this(numArguments, exceptionClass, null); } BytecodeExceptionKind(int numArguments, Class<? extends Throwable> exceptionClass, String exceptionMessage) { this.numArguments = numArguments; this.exceptionClass = exceptionClass; this.exceptionMessage = exceptionMessage; } public String getExceptionMessage() { return exceptionMessage; } } public static final NodeClass<BytecodeExceptionNode> TYPE = NodeClass.create(BytecodeExceptionNode.class); protected final BytecodeExceptionKind exceptionKind; @Input NodeInputList<ValueNode> arguments; public BytecodeExceptionNode(MetaAccessProvider metaAccess, BytecodeExceptionKind exceptionKind, ValueNode... arguments) { super(TYPE, StampFactory.objectNonNull(TypeReference.createExactTrusted(metaAccess.lookupJavaType(exceptionKind.exceptionClass)))); this.exceptionKind = exceptionKind; this.arguments = new NodeInputList<>(this, arguments); GraalError.guarantee(arguments.length == exceptionKind.numArguments, "Mismatch in argument count for BytecodeExceptionNode"); } public BytecodeExceptionKind getExceptionKind() { return exceptionKind; } @Override public String toString(Verbosity verbosity) { if (verbosity == Verbosity.Name) { return super.toString(verbosity) + "#" + exceptionKind; } return super.toString(verbosity); } @Override public LocationIdentity getKilledLocationIdentity() { return LocationIdentity.any(); } @Override public Node canonical(CanonicalizerTool tool) { if (tool.allUsagesAvailable() && (hasNoUsages() || (hasExactlyOneUsage() && usages().first() == stateAfter))) { return null; } return this; } public NodeInputList<ValueNode> getArguments() { return arguments; }
Create a new stateDuring for use by a foreign call.
/** * Create a new stateDuring for use by a foreign call. */
public FrameState createStateDuring() { boolean rethrowException = false; boolean duringCall = true; return stateAfter.duplicateModified(graph(), stateAfter.bci, rethrowException, duringCall, JavaKind.Object, null, null); } }