Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -382,14 +382,19 @@ public FrameState duplicateModified(JavaKind popKind, JavaKind pushedSlotKind, V
return duplicateModified(graph(), bci, rethrowException, duringCall, popKind, new JavaKind[]{pushedSlotKind}, new ValueNode[]{pushedValue}, pushedVirtualObjectMappings);
}

public FrameState duplicateModified(StructuredGraph graph, int newBci, boolean newRethrowException, boolean newDuringCall, JavaKind popKind, JavaKind[] pushedSlotKinds, ValueNode[] pushedValues,
List<EscapeObjectState> pushedVirtualObjectMappings) {
return duplicateModified(graph, newBci, newRethrowException, newDuringCall, popKind, pushedSlotKinds, pushedValues, pushedVirtualObjectMappings, true);
}

/**
* Creates a copy of this frame state with one stack element of type popKind popped from the
* stack and the values in pushedValues pushed on the stack. The pushedValues will be formatted
* correctly in slot encoding: a long or double will be followed by a null slot. The bci will be
* changed to newBci.
*/
public FrameState duplicateModified(StructuredGraph graph, int newBci, boolean newRethrowException, boolean newDuringCall, JavaKind popKind, JavaKind[] pushedSlotKinds, ValueNode[] pushedValues,
List<EscapeObjectState> pushedVirtualObjectMappings) {
List<EscapeObjectState> pushedVirtualObjectMappings, boolean checkStackDepth) {
List<EscapeObjectState> copiedVirtualObjectMappings = null;
ArrayList<ValueNode> copy;
if (newRethrowException && !rethrowException && popKind == JavaKind.Void) {
Expand Down Expand Up @@ -422,7 +427,7 @@ public FrameState duplicateModified(StructuredGraph graph, int newBci, boolean n
int newStackSize = copy.size() - localsSize;
copy.addAll(values.subList(localsSize + stackSize, values.size()));

assert checkStackDepth(bci, stackSize, duringCall, rethrowException, newBci, newStackSize, newDuringCall, newRethrowException);
assert !checkStackDepth || checkStackDepth(bci, stackSize, duringCall, rethrowException, newBci, newStackSize, newDuringCall, newRethrowException);
return graph.add(new FrameState(outerFrameState(), code, newBci, copy, localsSize, newStackSize, newRethrowException, newDuringCall, monitorIds,
copiedVirtualObjectMappings != null ? copiedVirtualObjectMappings : virtualObjectMappings));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public int getParameterCount(boolean receiver) {
public JavaType getParameterType(int index, ResolvedJavaType accessingClass) {
ResolvedJavaType parameterType;
try {
parameterType = wrapped.getParameterType(index, defaultAccessingClass).resolve(defaultAccessingClass);
parameterType = resolve(wrapped.getParameterType(index, defaultAccessingClass));
} catch (LinkageError e) {
/*
* Type resolution fails if the parameter type is missing. Just erase the type by
Expand All @@ -64,7 +64,7 @@ public JavaType getParameterType(int index, ResolvedJavaType accessingClass) {
public JavaType getReturnType(ResolvedJavaType accessingClass) {
ResolvedJavaType returnType;
try {
returnType = wrapped.getReturnType(defaultAccessingClass).resolve(defaultAccessingClass);
returnType = resolve(wrapped.getReturnType(defaultAccessingClass));
} catch (LinkageError e) {
/*
* Type resolution fails if the return type is missing. Just erase the type by returning
Expand All @@ -74,4 +74,18 @@ public JavaType getReturnType(ResolvedJavaType accessingClass) {
}
return universe.lookup(returnType);
}

/**
* We must not invoke {@link JavaType#resolve} on an already resolved type because it can
* actually fail the accessibility check when synthetic methods and synthetic signatures are
* involved.
*/
private ResolvedJavaType resolve(JavaType type) {
if (type instanceof ResolvedJavaType) {
return (ResolvedJavaType) type;
} else {
return type.resolve(defaultAccessingClass);
}
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 2021, 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
Expand Down Expand Up @@ -31,6 +31,7 @@
* of a constructor).
*/
@InternalVMMethod
@FactoryMethodMarker
public final class FactoryMethodHolder {
private FactoryMethodHolder() {
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2021, 2021, 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 com.oracle.svm.core.code;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FactoryMethodMarker {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright (c) 2021, 2021, 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 com.oracle.svm.core.code;

import com.oracle.svm.core.jdk.InternalVMMethod;

/**
* Holder class for generated factory methods (methods that combine object allocation and invocation
* of a constructor) that then immediately throw the allocated objects (which must be an exception
* type).
*/
@InternalVMMethod
@FactoryMethodMarker
public final class FactoryThrowMethodHolder {
private FactoryThrowMethodHolder() {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,32 +24,16 @@
*/
package com.oracle.svm.core.jdk;

import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.graalvm.util.DirectAnnotationAccess;

/**
* Annotation for types whose methods must be ignored for certain kinds of stack walks, such as by
* Reflection.getCallerClass(). All methods in the annotated type have the same level of visibility.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface InternalVMMethod {

@InternalVMMethod()
class Holder {

/** Instance of the annotation, useful when the annotation is manually injected. */
public static final InternalVMMethod INSTANCE = DirectAnnotationAccess.getAnnotation(Holder.class, InternalVMMethod.class);

/**
* Array that contains only the instance of the annotation, useful when the annotation is
* manually injected.
*/
public static final Annotation[] ARRAY = new Annotation[]{INSTANCE};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@

import com.oracle.svm.core.annotate.NeverInline;
import com.oracle.svm.core.jdk.InternalVMMethod;
import com.oracle.svm.core.reflect.SubstrateConstructorAccessor.ConstructorNewInstanceFunctionPointer;
import com.oracle.svm.core.reflect.SubstrateMethodAccessor.MethodInvokeFunctionPointer;
import com.oracle.svm.core.util.VMError;

Expand All @@ -47,21 +46,13 @@ public final class ReflectionAccessorHolder {
* Signature prototype for invoking a method via a {@link SubstrateMethodAccessor}. Must match
* the signature of {@link MethodInvokeFunctionPointer#invoke}
*/
static Object invokePrototype(boolean invokeSpecial, Object obj, Object[] args) {
throw VMError.shouldNotReachHere("Only used as a prototype for generated methods");
}

/**
* Signature prototype for allocating a new instance via a {@link SubstrateConstructorAccessor}.
* Must match * the signature of {@link ConstructorNewInstanceFunctionPointer#invoke}
*/
static Object newInstancePrototype(Object[] args) {
private static Object invokePrototype(boolean invokeSpecial, Object obj, Object[] args) {
throw VMError.shouldNotReachHere("Only used as a prototype for generated methods");
}

/*
* Methods for throwing exceptions when a method or constructor is used in an illegal way. These
* methods are invoked via function pointers, so must have the same signature as the prototypes
* methods are invoked via function pointers, so must have the same signature as the prototype
* above.
*/

Expand All @@ -70,7 +61,7 @@ private static void methodHandleInvokeError(boolean invokeSpecial, Object obj, O
throw new InvocationTargetException(new UnsupportedOperationException("MethodHandle.invoke() and MethodHandle.invokeExact() cannot be invoked through reflection"));
}

private static Object newInstanceError(Object[] args) throws InstantiationException {
private static Object newInstanceError(boolean invokeSpecial, Object obj, Object[] args) throws InstantiationException {
throw new InstantiationException("Only non-abstract instance classes can be instantiated using reflection");
}

Expand All @@ -80,30 +71,25 @@ private static Object newInstanceError(Object[] args) throws InstantiationExcept
*/

@NeverInline("Exception slow path")
private static InvocationTargetException throwInvocationTargetException(Throwable target) throws InvocationTargetException {
throw new InvocationTargetException(target);
}

@NeverInline("Exception slow path")
private static void throwIllegalArgumentExceptionForMethod(Object member, Object obj, Object[] args) {
throwIllegalArgumentException(member, false, obj, args);
private static void throwIllegalArgumentExceptionWithReceiver(Object member, Object obj, Object[] args) {
throwIllegalArgumentException(member, true, obj, args);
}

@NeverInline("Exception slow path")
private static void throwIllegalArgumentExceptionForConstructor(Object member, Object[] args) {
throwIllegalArgumentException(member, true, null, args);
private static void throwIllegalArgumentExceptionWithoutReceiver(Object member, Object[] args) {
throwIllegalArgumentException(member, false, null, args);
}

/**
* We do not know which check in the generated metod caused the exception, so we cannot print
* We do not know which check in the generated method caused the exception, so we cannot print
* detailed information about that. But printing the signature of the method and all the types
* of the actual arguments should make it obvious what the problem is.
*/
private static void throwIllegalArgumentException(Object member, boolean constructor, Object obj, Object[] args) {
private static void throwIllegalArgumentException(Object member, boolean withReceiver, Object obj, Object[] args) {
String sep = System.lineSeparator();
StringBuilder msg = new StringBuilder();
msg.append("Illegal arguments for invoking ").append(member);
if (!constructor) {
if (withReceiver) {
msg.append(sep).append(" obj: ").append(obj == null ? "null" : obj.getClass().getTypeName());
}
if (args == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,13 @@

import org.graalvm.nativeimage.c.function.CFunctionPointer;

import com.oracle.svm.core.annotate.InvokeJavaFunctionPointer;
import com.oracle.svm.core.jdk.InternalVMMethod;
import com.oracle.svm.core.reflect.SubstrateMethodAccessor.MethodInvokeFunctionPointer;
import com.oracle.svm.core.util.VMError;

@InternalVMMethod
public abstract class SubstrateConstructorAccessor {

interface ConstructorNewInstanceFunctionPointer extends CFunctionPointer {
/** Must match the signature of {@link ReflectionAccessorHolder#newInstancePrototype}. */
@InvokeJavaFunctionPointer
Object invoke(Object[] args);
}

private final Executable member;
private final CFunctionPointer newInstanceFunctionPointer;

Expand All @@ -52,11 +46,11 @@ protected SubstrateConstructorAccessor(Executable member, CFunctionPointer newIn
}

public Object newInstance(Object[] args) {
ConstructorNewInstanceFunctionPointer functionPointer = (ConstructorNewInstanceFunctionPointer) this.newInstanceFunctionPointer;
MethodInvokeFunctionPointer functionPointer = (MethodInvokeFunctionPointer) this.newInstanceFunctionPointer;
if (functionPointer.isNull()) {
throw newInstanceError();
}
return functionPointer.invoke(args);
return functionPointer.invoke(false, null, args);
}

private RuntimeException newInstanceError() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

import com.oracle.svm.core.SubstrateDiagnostics;
import com.oracle.svm.core.annotate.RestrictHeapAccess;
import com.oracle.svm.core.code.FactoryMethodMarker;
import com.oracle.svm.core.jdk.InternalVMMethod;
import com.oracle.svm.core.jdk.StackTraceUtils;
import com.oracle.svm.core.snippets.SnippetRuntime.SubstrateForeignCallDescriptor;
Expand All @@ -45,6 +46,7 @@
* therefore these methods are filtered in exception stack traces (see {@link StackTraceUtils}).
*/
@InternalVMMethod
@FactoryMethodMarker
public class ImplicitExceptions {
public static final String NO_STACK_MSG = "[no exception stack trace available because exception is thrown from code that must be allocation free]";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,11 @@ public void methodAfterParsingHook(BigBang bb, AnalysisMethod method, Structured

if (parseOnce) {
optimizeAfterParsing(bb, graph);
/*
* Do a complete Canonicalizer run once before graph encoding, to clean up any
* leftover uncanonicalized nodes.
*/
CanonicalizerPhase.create().apply(graph, bb.getProviders());
}

for (BiConsumer<AnalysisMethod, StructuredGraph> methodAfterParsingHook : methodAfterParsingHooks) {
Expand All @@ -571,11 +576,6 @@ protected void optimizeAfterParsing(BigBang bb, StructuredGraph graph) {
new ImplicitAssertionsPhase().apply(graph, bb.getProviders());
new BoxNodeIdentityPhase().apply(graph, bb.getProviders());
new PartialEscapePhase(false, false, CanonicalizerPhase.create(), null, options).apply(graph, bb.getProviders());
/*
* Do a complete Canonicalizer run once before graph encoding, to clean up any leftover
* uncanonicalized nodes.
*/
CanonicalizerPhase.create().apply(graph, bb.getProviders());
}

@Override
Expand Down
Loading