use of org.graalvm.compiler.nodes.UnwindNode in project graal by oracle.
the class DeletedMethod method buildGraph.
public static StructuredGraph buildGraph(DebugContext debug, ResolvedJavaMethod method, HostedProviders providers, String message) {
HostedGraphKit kit = new HostedGraphKit(debug, providers, method);
StructuredGraph graph = kit.getGraph();
FrameStateBuilder state = new FrameStateBuilder(null, method, graph);
state.initializeForMethodStart(null, true, providers.getGraphBuilderPlugins());
/*
* A random, but unique and consistent, number for every invoke. This is necessary because
* we, e.g., look up static analysis results by bci.
*/
int bci = 0;
graph.start().setStateAfter(state.create(bci++, graph.start()));
String msg = AnnotationSubstitutionProcessor.deleteErrorMessage(method, message, false);
ValueNode msgNode = ConstantNode.forConstant(SubstrateObjectConstant.forObject(msg), providers.getMetaAccess(), graph);
ValueNode exceptionNode = kit.createInvokeWithExceptionAndUnwind(providers.getMetaAccess().lookupJavaMethod(reportErrorMethod), InvokeKind.Static, state, bci++, bci++, msgNode);
kit.append(new UnwindNode(exceptionNode));
kit.mergeUnwinds();
assert graph.verify();
return graph;
}
use of org.graalvm.compiler.nodes.UnwindNode in project graal by oracle.
the class GraphKit method createInvokeWithExceptionAndUnwind.
@SuppressWarnings("try")
public InvokeWithExceptionNode createInvokeWithExceptionAndUnwind(ResolvedJavaMethod method, InvokeKind invokeKind, FrameStateBuilder frameStateBuilder, int invokeBci, int exceptionEdgeBci, ValueNode... args) {
try (DebugCloseable context = graph.withNodeSourcePosition(NodeSourcePosition.substitution(graph.currentNodeSourcePosition(), method))) {
InvokeWithExceptionNode result = startInvokeWithException(method, invokeKind, frameStateBuilder, invokeBci, exceptionEdgeBci, args);
exceptionPart();
ExceptionObjectNode exception = exceptionObject();
append(new UnwindNode(exception));
endInvokeWithException();
return result;
}
}
use of org.graalvm.compiler.nodes.UnwindNode in project graal by oracle.
the class PEGraphDecoder method finishInlining.
@Override
protected void finishInlining(MethodScope is) {
PEMethodScope inlineScope = (PEMethodScope) is;
ResolvedJavaMethod inlineMethod = inlineScope.method;
PEMethodScope methodScope = inlineScope.caller;
LoopScope loopScope = inlineScope.callerLoopScope;
InvokeData invokeData = inlineScope.invokeData;
Invoke invoke = invokeData.invoke;
FixedNode invokeNode = invoke.asNode();
ValueNode exceptionValue = null;
int returnNodeCount = 0;
int unwindNodeCount = 0;
List<ControlSinkNode> returnAndUnwindNodes = inlineScope.returnAndUnwindNodes;
for (int i = 0; i < returnAndUnwindNodes.size(); i++) {
FixedNode fixedNode = returnAndUnwindNodes.get(i);
if (fixedNode instanceof ReturnNode) {
returnNodeCount++;
} else if (fixedNode.isAlive()) {
assert fixedNode instanceof UnwindNode;
unwindNodeCount++;
}
}
if (unwindNodeCount > 0) {
FixedNode unwindReplacement;
if (invoke instanceof InvokeWithExceptionNode) {
/* Decoding continues for the exception handler. */
unwindReplacement = makeStubNode(methodScope, loopScope, invokeData.exceptionNextOrderId);
} else {
/* No exception handler available, so the only thing we can do is deoptimize. */
unwindReplacement = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler));
}
if (unwindNodeCount == 1) {
/* Only one UnwindNode, we can use the exception directly. */
UnwindNode unwindNode = getSingleMatchingNode(returnAndUnwindNodes, returnNodeCount > 0, UnwindNode.class);
exceptionValue = unwindNode.exception();
unwindNode.replaceAndDelete(unwindReplacement);
} else {
/*
* More than one UnwindNode. This can happen with the loop explosion strategy
* FULL_EXPLODE_UNTIL_RETURN, where we keep exploding after the loop and therefore
* also explode exception paths. Merge the exception in a similar way as multiple
* return values.
*/
MergeNode unwindMergeNode = graph.add(new MergeNode());
exceptionValue = InliningUtil.mergeValueProducers(unwindMergeNode, getMatchingNodes(returnAndUnwindNodes, returnNodeCount > 0, UnwindNode.class, unwindNodeCount), null, unwindNode -> unwindNode.exception());
unwindMergeNode.setNext(unwindReplacement);
ensureExceptionStateDecoded(inlineScope);
unwindMergeNode.setStateAfter(inlineScope.exceptionState.duplicateModified(JavaKind.Object, JavaKind.Object, exceptionValue));
}
}
assert invoke.next() == null;
assert !(invoke instanceof InvokeWithExceptionNode) || ((InvokeWithExceptionNode) invoke).exceptionEdge() == null;
ValueNode returnValue;
if (returnNodeCount == 0) {
returnValue = null;
} else if (returnNodeCount == 1) {
ReturnNode returnNode = getSingleMatchingNode(returnAndUnwindNodes, unwindNodeCount > 0, ReturnNode.class);
returnValue = returnNode.result();
FixedNode n = nodeAfterInvoke(methodScope, loopScope, invokeData, AbstractBeginNode.prevBegin(returnNode));
returnNode.replaceAndDelete(n);
} else {
AbstractMergeNode merge = graph.add(new MergeNode());
merge.setStateAfter((FrameState) ensureNodeCreated(methodScope, loopScope, invokeData.stateAfterOrderId));
returnValue = InliningUtil.mergeReturns(merge, getMatchingNodes(returnAndUnwindNodes, unwindNodeCount > 0, ReturnNode.class, returnNodeCount));
FixedNode n = nodeAfterInvoke(methodScope, loopScope, invokeData, merge);
merge.setNext(n);
}
invokeNode.replaceAtUsages(returnValue);
/*
* Usage the handles that we have on the return value and the exception to update the
* orderId->Node table.
*/
registerNode(loopScope, invokeData.invokeOrderId, returnValue, true, true);
if (invoke instanceof InvokeWithExceptionNode) {
registerNode(loopScope, invokeData.exceptionOrderId, exceptionValue, true, true);
}
if (inlineScope.exceptionPlaceholderNode != null) {
inlineScope.exceptionPlaceholderNode.replaceAtUsagesAndDelete(exceptionValue);
}
deleteInvoke(invoke);
for (InlineInvokePlugin plugin : inlineInvokePlugins) {
plugin.notifyAfterInline(inlineMethod);
}
}
use of org.graalvm.compiler.nodes.UnwindNode in project graal by oracle.
the class CFunctionCallStubMethod method adaptSignatureAndConvertArguments.
private static Signature adaptSignatureAndConvertArguments(ResolvedJavaMethod method, HostedProviders providers, NativeLibraries nativeLibraries, HostedGraphKit kit, Signature signature, List<ValueNode> arguments) {
MetaAccessProvider metaAccess = providers.getMetaAccess();
JavaType returnType = signature.getReturnType(null);
JavaType[] parameterTypes = signature.toParameterTypes(null);
for (int i = 0; i < parameterTypes.length; i++) {
if (!isPrimitiveOrWord(providers, parameterTypes[i])) {
ElementInfo typeInfo = nativeLibraries.findElementInfo(parameterTypes[i]);
if (typeInfo instanceof EnumInfo) {
UserError.guarantee(typeInfo.getChildren().stream().anyMatch(EnumValueInfo.class::isInstance), "Enum class " + returnType.toJavaName() + " needs a method that is annotated with @" + CEnumValue.class.getSimpleName() + " because it is used as a parameter of a method annotated with @" + CFunction.class.getSimpleName() + ": " + method.format("%H.%n(%p)"));
ValueNode argumentValue = arguments.get(i);
IsNullNode isNull = kit.unique(new IsNullNode(argumentValue));
kit.startIf(isNull, BranchProbabilityNode.VERY_SLOW_PATH_PROBABILITY);
kit.thenPart();
ResolvedJavaType enumExceptionType = metaAccess.lookupJavaType(RuntimeException.class);
NewInstanceNode enumException = kit.append(new NewInstanceNode(enumExceptionType, true));
Iterator<ResolvedJavaMethod> enumExceptionCtor = Arrays.stream(enumExceptionType.getDeclaredConstructors()).filter(c -> c.getSignature().getParameterCount(false) == 1 && c.getSignature().getParameterType(0, null).equals(metaAccess.lookupJavaType(String.class))).iterator();
ConstantNode enumExceptionMessage = kit.createConstant(kit.getConstantReflection().forString("null return value cannot be converted to a C enum value"), JavaKind.Object);
kit.createJavaCallWithExceptionAndUnwind(InvokeKind.Special, enumExceptionCtor.next(), enumException, enumExceptionMessage);
assert !enumExceptionCtor.hasNext();
kit.append(new UnwindNode(enumException));
kit.endIf();
CInterfaceEnumTool tool = new CInterfaceEnumTool(metaAccess, providers.getSnippetReflection());
argumentValue = tool.createEnumValueInvoke(kit, (EnumInfo) typeInfo, cEnumKind, argumentValue);
arguments.set(i, argumentValue);
parameterTypes[i] = metaAccess.lookupJavaType(cEnumKind.toJavaClass());
} else {
throw UserError.abort("@" + CFunction.class.getSimpleName() + " parameter types are restricted to primitive types, word types and enumerations (@" + CEnum.class.getSimpleName() + "): " + method.format("%H.%n(%p)"));
}
}
}
if (!isPrimitiveOrWord(providers, returnType)) {
// Assume enum: actual checks and conversion are in adaptReturnValue()
returnType = providers.getWordTypes().getWordImplType();
}
JavaType actualReturnType = returnType;
return new Signature() {
@Override
public int getParameterCount(boolean receiver) {
return parameterTypes.length;
}
@Override
public JavaType getParameterType(int index, ResolvedJavaType accessingClass) {
return parameterTypes[index];
}
@Override
public JavaType getReturnType(ResolvedJavaType accessingClass) {
return actualReturnType;
}
};
}
use of org.graalvm.compiler.nodes.UnwindNode in project graal by oracle.
the class DefaultHotSpotLoweringProvider method lower.
@Override
public void lower(Node n, LoweringTool tool) {
StructuredGraph graph = (StructuredGraph) n.graph();
if (n instanceof Invoke) {
lowerInvoke((Invoke) n, tool, graph);
} else if (n instanceof LoadMethodNode) {
lowerLoadMethodNode((LoadMethodNode) n);
} else if (n instanceof GetClassNode) {
lowerGetClassNode((GetClassNode) n, tool, graph);
} else if (n instanceof StoreHubNode) {
lowerStoreHubNode((StoreHubNode) n, graph);
} else if (n instanceof OSRStartNode) {
lowerOSRStartNode((OSRStartNode) n);
} else if (n instanceof BytecodeExceptionNode) {
lowerBytecodeExceptionNode((BytecodeExceptionNode) n);
} else if (n instanceof InstanceOfNode) {
InstanceOfNode instanceOfNode = (InstanceOfNode) n;
if (graph.getGuardsStage().areDeoptsFixed()) {
instanceofSnippets.lower(instanceOfNode, tool);
} else {
if (instanceOfNode.allowsNull()) {
ValueNode object = instanceOfNode.getValue();
LogicNode newTypeCheck = graph.addOrUniqueWithInputs(InstanceOfNode.create(instanceOfNode.type(), object, instanceOfNode.profile(), instanceOfNode.getAnchor()));
LogicNode newNode = LogicNode.or(graph.unique(IsNullNode.create(object)), newTypeCheck, GraalDirectives.UNLIKELY_PROBABILITY);
instanceOfNode.replaceAndDelete(newNode);
}
}
} else if (n instanceof InstanceOfDynamicNode) {
InstanceOfDynamicNode instanceOfDynamicNode = (InstanceOfDynamicNode) n;
if (graph.getGuardsStage().areDeoptsFixed()) {
instanceofSnippets.lower(instanceOfDynamicNode, tool);
} else {
ValueNode mirror = instanceOfDynamicNode.getMirrorOrHub();
if (mirror.stamp(NodeView.DEFAULT).getStackKind() == JavaKind.Object) {
ClassGetHubNode classGetHub = graph.unique(new ClassGetHubNode(mirror));
instanceOfDynamicNode.setMirror(classGetHub);
}
if (instanceOfDynamicNode.allowsNull()) {
ValueNode object = instanceOfDynamicNode.getObject();
LogicNode newTypeCheck = graph.addOrUniqueWithInputs(InstanceOfDynamicNode.create(graph.getAssumptions(), tool.getConstantReflection(), instanceOfDynamicNode.getMirrorOrHub(), object, false));
LogicNode newNode = LogicNode.or(graph.unique(IsNullNode.create(object)), newTypeCheck, GraalDirectives.UNLIKELY_PROBABILITY);
instanceOfDynamicNode.replaceAndDelete(newNode);
}
}
} else if (n instanceof ClassIsAssignableFromNode) {
if (graph.getGuardsStage().areDeoptsFixed()) {
instanceofSnippets.lower((ClassIsAssignableFromNode) n, tool);
}
} else if (n instanceof NewInstanceNode) {
if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
newObjectSnippets.lower((NewInstanceNode) n, registers, tool);
}
} else if (n instanceof DynamicNewInstanceNode) {
DynamicNewInstanceNode newInstanceNode = (DynamicNewInstanceNode) n;
if (newInstanceNode.getClassClass() == null) {
JavaConstant classClassMirror = constantReflection.forObject(Class.class);
ConstantNode classClass = ConstantNode.forConstant(classClassMirror, tool.getMetaAccess(), graph);
newInstanceNode.setClassClass(classClass);
}
if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
newObjectSnippets.lower(newInstanceNode, registers, tool);
}
} else if (n instanceof NewArrayNode) {
if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
newObjectSnippets.lower((NewArrayNode) n, registers, tool);
}
} else if (n instanceof DynamicNewArrayNode) {
DynamicNewArrayNode dynamicNewArrayNode = (DynamicNewArrayNode) n;
if (dynamicNewArrayNode.getVoidClass() == null) {
JavaConstant voidClassMirror = constantReflection.forObject(void.class);
ConstantNode voidClass = ConstantNode.forConstant(voidClassMirror, tool.getMetaAccess(), graph);
dynamicNewArrayNode.setVoidClass(voidClass);
}
if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
newObjectSnippets.lower(dynamicNewArrayNode, registers, tool);
}
} else if (n instanceof VerifyHeapNode) {
if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
newObjectSnippets.lower((VerifyHeapNode) n, registers, tool);
}
} else if (n instanceof RawMonitorEnterNode) {
if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
monitorSnippets.lower((RawMonitorEnterNode) n, registers, tool);
}
} else if (n instanceof MonitorExitNode) {
if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
monitorSnippets.lower((MonitorExitNode) n, registers, tool);
}
} else if (n instanceof ArrayCopyNode) {
arraycopySnippets.lower((ArrayCopyNode) n, tool);
} else if (n instanceof ArrayCopyWithSlowPathNode) {
arraycopySnippets.lower((ArrayCopyWithSlowPathNode) n, tool);
} else if (n instanceof G1PreWriteBarrier) {
writeBarrierSnippets.lower((G1PreWriteBarrier) n, registers, tool);
} else if (n instanceof G1PostWriteBarrier) {
writeBarrierSnippets.lower((G1PostWriteBarrier) n, registers, tool);
} else if (n instanceof G1ReferentFieldReadBarrier) {
writeBarrierSnippets.lower((G1ReferentFieldReadBarrier) n, registers, tool);
} else if (n instanceof SerialWriteBarrier) {
writeBarrierSnippets.lower((SerialWriteBarrier) n, tool);
} else if (n instanceof SerialArrayRangeWriteBarrier) {
writeBarrierSnippets.lower((SerialArrayRangeWriteBarrier) n, tool);
} else if (n instanceof G1ArrayRangePreWriteBarrier) {
writeBarrierSnippets.lower((G1ArrayRangePreWriteBarrier) n, registers, tool);
} else if (n instanceof G1ArrayRangePostWriteBarrier) {
writeBarrierSnippets.lower((G1ArrayRangePostWriteBarrier) n, registers, tool);
} else if (n instanceof NewMultiArrayNode) {
if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
newObjectSnippets.lower((NewMultiArrayNode) n, tool);
}
} else if (n instanceof LoadExceptionObjectNode) {
exceptionObjectSnippets.lower((LoadExceptionObjectNode) n, registers, tool);
} else if (n instanceof AssertionNode) {
assertionSnippets.lower((AssertionNode) n, tool);
} else if (n instanceof StringToBytesNode) {
if (graph.getGuardsStage().areDeoptsFixed()) {
stringToBytesSnippets.lower((StringToBytesNode) n, tool);
}
} else if (n instanceof IntegerDivRemNode) {
// Nothing to do for division nodes. The HotSpot signal handler catches divisions by
// zero and the MIN_VALUE / -1 cases.
} else if (n instanceof AbstractDeoptimizeNode || n instanceof UnwindNode || n instanceof RemNode || n instanceof SafepointNode) {
/* No lowering, we generate LIR directly for these nodes. */
} else if (n instanceof ClassGetHubNode) {
lowerClassGetHubNode((ClassGetHubNode) n, tool);
} else if (n instanceof HubGetClassNode) {
lowerHubGetClassNode((HubGetClassNode) n, tool);
} else if (n instanceof KlassLayoutHelperNode) {
lowerKlassLayoutHelperNode((KlassLayoutHelperNode) n, tool);
} else if (n instanceof ComputeObjectAddressNode) {
if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
lowerComputeObjectAddressNode((ComputeObjectAddressNode) n);
}
} else if (n instanceof IdentityHashCodeNode) {
hashCodeSnippets.lower((IdentityHashCodeNode) n, tool);
} else if (n instanceof ResolveDynamicConstantNode) {
if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
resolveConstantSnippets.lower((ResolveDynamicConstantNode) n, tool);
}
} else if (n instanceof ResolveConstantNode) {
if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
resolveConstantSnippets.lower((ResolveConstantNode) n, tool);
}
} else if (n instanceof ResolveMethodAndLoadCountersNode) {
if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
resolveConstantSnippets.lower((ResolveMethodAndLoadCountersNode) n, tool);
}
} else if (n instanceof InitializeKlassNode) {
if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
resolveConstantSnippets.lower((InitializeKlassNode) n, tool);
}
} else if (n instanceof ProfileNode) {
profileSnippets.lower((ProfileNode) n, tool);
} else {
super.lower(n, tool);
}
}
Aggregations