use of com.oracle.graal.pointsto.phases.NoClassInitializationPlugin in project graal by oracle.
the class IntrinsifyMethodHandlesInvocationPlugin method processInvokeWithMethodHandle.
@SuppressWarnings("try")
private boolean processInvokeWithMethodHandle(GraphBuilderContext b, Replacements replacements, ResolvedJavaMethod methodHandleMethod, ValueNode[] methodHandleArguments) {
/*
* When parsing for compilation, we must not intrinsify method handles that were not
* intrinsified during analysis. Otherwise new code that was not seen as reachable by the
* static analysis would be compiled.
*/
if (reason != ParsingReason.PointsToAnalysis && intrinsificationRegistry.get(b.getMethod(), b.bci()) != Boolean.TRUE) {
return false;
}
Plugins graphBuilderPlugins = new Plugins(parsingProviders.getReplacements().getGraphBuilderPlugins());
registerInvocationPlugins(graphBuilderPlugins.getInvocationPlugins(), replacements);
graphBuilderPlugins.prependParameterPlugin(new MethodHandlesParameterPlugin(methodHandleArguments));
graphBuilderPlugins.clearInlineInvokePlugins();
graphBuilderPlugins.prependInlineInvokePlugin(new MethodHandlesInlineInvokePlugin());
graphBuilderPlugins.prependNodePlugin(new MethodHandlePlugin(parsingProviders.getConstantReflection().getMethodHandleAccess(), false));
/* We do all the word type rewriting because parameters to the lambda can be word types. */
SnippetReflectionProvider originalSnippetReflection = GraalAccess.getOriginalSnippetReflection();
WordOperationPlugin wordOperationPlugin = new WordOperationPlugin(originalSnippetReflection, new SubstrateWordTypes(parsingProviders.getMetaAccess(), FrameAccess.getWordKind()));
graphBuilderPlugins.appendInlineInvokePlugin(wordOperationPlugin);
graphBuilderPlugins.appendTypePlugin(wordOperationPlugin);
graphBuilderPlugins.appendTypePlugin(new TrustedInterfaceTypePlugin());
graphBuilderPlugins.appendNodePlugin(wordOperationPlugin);
graphBuilderPlugins.setClassInitializationPlugin(new NoClassInitializationPlugin());
GraphBuilderConfiguration graphBuilderConfig = GraphBuilderConfiguration.getSnippetDefault(graphBuilderPlugins);
GraphBuilderPhase.Instance graphBuilder = new GraphBuilderPhase.Instance(parsingProviders, graphBuilderConfig, OptimisticOptimizations.NONE, null);
DebugContext debug = b.getDebug();
StructuredGraph graph = new StructuredGraph.Builder(b.getOptions(), debug).method(NativeImageUtil.toOriginal(methodHandleMethod)).build();
try (DebugContext.Scope s = debug.scope("IntrinsifyMethodHandles", graph)) {
graphBuilder.apply(graph);
/*
* The canonicalizer converts unsafe field accesses for get/set method handles back to
* high-level field load and store nodes.
*/
CanonicalizerPhase.create().apply(graph, parsingProviders);
debug.dump(DebugContext.VERBOSE_LEVEL, graph, "Intrinisfication graph before transplant");
NodeMap<Node> transplanted = new NodeMap<>(graph);
for (ParameterNode oParam : graph.getNodes(ParameterNode.TYPE)) {
transplanted.put(oParam, methodHandleArguments[oParam.index()]);
}
Transplanter transplanter = new Transplanter(b, transplanted);
try {
transplanter.graph(graph);
if (reason == ParsingReason.PointsToAnalysis) {
/*
* Successfully intrinsified during analysis, remember that we can intrinsify
* when parsing for compilation.
*/
intrinsificationRegistry.add(b.getMethod(), b.bci(), Boolean.TRUE);
}
return true;
} catch (AbortTransplantException ex) {
/*
* The method handle cannot be intrinsified. If non-constant method handles are not
* supported, the code that throws an error at runtime was already appended, so
* nothing more to do. If non-constant method handles are supported, we return false
* so that the bytecode parser emit a regular invoke bytecode, i.e., the constant
* method handle is treated as if it were non-constant.
*/
return ex.handled;
}
} catch (Throwable ex) {
throw debug.handle(ex);
}
}
use of com.oracle.graal.pointsto.phases.NoClassInitializationPlugin in project graal by oracle.
the class UnsafeAutomaticSubstitutionProcessor method init.
public void init(ImageClassLoader loader, MetaAccessProvider originalMetaAccess) {
ResolvedJavaMethod atomicIntegerFieldUpdaterNewUpdaterMethod;
ResolvedJavaMethod atomicLongFieldUpdaterNewUpdaterMethod;
ResolvedJavaMethod atomicReferenceFieldUpdaterNewUpdaterMethod;
ResolvedJavaMethod fieldSetAccessibleMethod;
ResolvedJavaMethod fieldGetMethod;
try {
Method fieldSetAccessible = Field.class.getMethod("setAccessible", boolean.class);
fieldSetAccessibleMethod = originalMetaAccess.lookupJavaMethod(fieldSetAccessible);
neverInlineSet.add(fieldSetAccessibleMethod);
Method fieldGet = Field.class.getMethod("get", Object.class);
fieldGetMethod = originalMetaAccess.lookupJavaMethod(fieldGet);
neverInlineSet.add(fieldGetMethod);
/*
* Various factory methods in VarHandle query the array base/index or field offsets.
* There is no need to analyze these calls because VarHandle accesses are intrinsified
* to simple array and field access nodes in IntrinsifyMethodHandlesInvocationPlugin.
*/
for (Method method : loader.findClassOrFail("java.lang.invoke.VarHandles").getDeclaredMethods()) {
neverInlineSet.add(originalMetaAccess.lookupJavaMethod(method));
}
Class<?> unsafeClass;
Class<?> sunMiscUnsafeClass;
try {
sunMiscUnsafeClass = Class.forName("sun.misc.Unsafe");
unsafeClass = Class.forName("jdk.internal.misc.Unsafe");
} catch (ClassNotFoundException cnfe) {
throw VMError.shouldNotReachHere(cnfe);
}
resolvedUnsafeClass = originalMetaAccess.lookupJavaType(unsafeClass);
resolvedSunMiscUnsafeClass = originalMetaAccess.lookupJavaType(sunMiscUnsafeClass);
Method unsafeObjectFieldOffset = unsafeClass.getMethod("objectFieldOffset", java.lang.reflect.Field.class);
unsafeObjectFieldOffsetFieldMethod = originalMetaAccess.lookupJavaMethod(unsafeObjectFieldOffset);
noCheckedExceptionsSet.add(unsafeObjectFieldOffsetFieldMethod);
neverInlineSet.add(unsafeObjectFieldOffsetFieldMethod);
Method unsafeObjectClassStringOffset = unsafeClass.getMethod("objectFieldOffset", java.lang.Class.class, String.class);
unsafeObjectFieldOffsetClassStringMethod = originalMetaAccess.lookupJavaMethod(unsafeObjectClassStringOffset);
noCheckedExceptionsSet.add(unsafeObjectFieldOffsetClassStringMethod);
neverInlineSet.add(unsafeObjectFieldOffsetClassStringMethod);
if (JavaVersionUtil.JAVA_SPEC >= 17) {
/*
* JDK 17 and later add checks for hidden classes and record classes in
* sun.misc.Unsafe before delegating to jdk.internal.misc.Unsafe. When inlined, the
* checks make control flow too complex to detect offset field assignments.
*/
Method sunMiscUnsafeObjectFieldOffset = sunMiscUnsafeClass.getMethod("objectFieldOffset", java.lang.reflect.Field.class);
sunMiscUnsafeObjectFieldOffsetMethod = originalMetaAccess.lookupJavaMethod(sunMiscUnsafeObjectFieldOffset);
noCheckedExceptionsSet.add(sunMiscUnsafeObjectFieldOffsetMethod);
neverInlineSet.add(sunMiscUnsafeObjectFieldOffsetMethod);
}
Method unsafeArrayBaseOffset = unsafeClass.getMethod("arrayBaseOffset", java.lang.Class.class);
unsafeArrayBaseOffsetMethod = originalMetaAccess.lookupJavaMethod(unsafeArrayBaseOffset);
noCheckedExceptionsSet.add(unsafeArrayBaseOffsetMethod);
neverInlineSet.add(unsafeArrayBaseOffsetMethod);
Method unsafeArrayIndexScale = unsafeClass.getMethod("arrayIndexScale", java.lang.Class.class);
unsafeArrayIndexScaleMethod = originalMetaAccess.lookupJavaMethod(unsafeArrayIndexScale);
noCheckedExceptionsSet.add(unsafeArrayIndexScaleMethod);
neverInlineSet.add(unsafeArrayIndexScaleMethod);
Method integerNumberOfLeadingZeros = java.lang.Integer.class.getMethod("numberOfLeadingZeros", int.class);
integerNumberOfLeadingZerosMethod = originalMetaAccess.lookupJavaMethod(integerNumberOfLeadingZeros);
neverInlineSet.add(integerNumberOfLeadingZerosMethod);
Method atomicIntegerFieldUpdaterNewUpdater = java.util.concurrent.atomic.AtomicIntegerFieldUpdater.class.getMethod("newUpdater", Class.class, String.class);
atomicIntegerFieldUpdaterNewUpdaterMethod = originalMetaAccess.lookupJavaMethod(atomicIntegerFieldUpdaterNewUpdater);
neverInlineSet.add(atomicIntegerFieldUpdaterNewUpdaterMethod);
Method atomicLongFieldUpdaterNewUpdater = java.util.concurrent.atomic.AtomicLongFieldUpdater.class.getMethod("newUpdater", Class.class, String.class);
atomicLongFieldUpdaterNewUpdaterMethod = originalMetaAccess.lookupJavaMethod(atomicLongFieldUpdaterNewUpdater);
neverInlineSet.add(atomicLongFieldUpdaterNewUpdaterMethod);
Method atomicReferenceFieldUpdaterNewUpdater = java.util.concurrent.atomic.AtomicReferenceFieldUpdater.class.getMethod("newUpdater", Class.class, Class.class, String.class);
atomicReferenceFieldUpdaterNewUpdaterMethod = originalMetaAccess.lookupJavaMethod(atomicReferenceFieldUpdaterNewUpdater);
neverInlineSet.add(atomicReferenceFieldUpdaterNewUpdaterMethod);
} catch (NoSuchMethodException e) {
throw VMError.shouldNotReachHere(e);
}
/*
* Create the GraphBuilderPhase which builds the graph for the static initializers.
*
* The builder phase will inline the first level callees to detect cases where the offset
* computation is performed by methods that wrap over the unsafe API. There are two
* exceptions:
*
* 1. Don't inline the invokes that we are trying to match.
*
* 2. Don't inline Atomic*FieldUpdater.newUpdater() methods as they lead to false errors.
* These methods reach calls to Unsafe.objectFieldOffset() whose value is recomputed by
* RecomputeFieldValue.Kind.AtomicFieldUpdaterOffset.
*/
StaticInitializerInlineInvokePlugin inlineInvokePlugin = new StaticInitializerInlineInvokePlugin(neverInlineSet);
plugins = new Plugins(new InvocationPlugins());
plugins.appendInlineInvokePlugin(inlineInvokePlugin);
NoClassInitializationPlugin classInitializationPlugin = new NoClassInitializationPlugin();
plugins.setClassInitializationPlugin(classInitializationPlugin);
ReflectionPlugins.registerInvocationPlugins(loader, snippetReflection, annotationSubstitutions, classInitializationPlugin, plugins.getInvocationPlugins(), null, ParsingReason.UnsafeSubstitutionAnalysis);
/*
* Analyzing certain classes leads to false errors. We disable reporting for those classes
* by default.
*/
try {
suppressWarnings.add(originalMetaAccess.lookupJavaType(Class.forName("sun.security.provider.ByteArrayAccess")));
} catch (ClassNotFoundException e) {
throw VMError.shouldNotReachHere(e);
}
}
use of com.oracle.graal.pointsto.phases.NoClassInitializationPlugin in project graal by oracle.
the class LambdaProxyRenamingSubstitutionProcessor method getSubstitution.
private LambdaSubstitutionType getSubstitution(ResolvedJavaType original) {
return typeSubstitutions.computeIfAbsent(original, (key) -> {
OptionValues options = bb.getOptions();
DebugContext debug = new Builder(options, new GraalDebugHandlersFactory(bb.getProviders().getSnippetReflection())).build();
Providers providers = GraalAccess.getOriginalProviders();
String lambdaTargetName = LambdaUtils.findStableLambdaName(new NoClassInitializationPlugin(), providers, key, options, debug, this);
return new LambdaSubstitutionType(key, findUniqueLambdaProxyName(lambdaTargetName));
});
}
Aggregations