use of org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.RequiredInvocationPlugin in project graal by oracle.
the class SubstrateGraphBuilderPlugins method registerKnownIntrinsicsPlugins.
private static void registerKnownIntrinsicsPlugins(InvocationPlugins plugins) {
Registration r = new Registration(plugins, KnownIntrinsics.class);
r.register(new RequiredInvocationPlugin("heapBase") {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
b.addPush(JavaKind.Object, ReadReservedRegister.createReadHeapBaseNode(b.getGraph()));
return true;
}
});
r.register(new RequiredInvocationPlugin("readHub", Object.class) {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode object) {
ValueNode nonNullObject = b.nullCheckedValue(object);
b.addPush(JavaKind.Object, new LoadHubNode(b.getStampProvider(), nonNullObject));
return true;
}
});
r.register(new RequiredInvocationPlugin("nonNullPointer", Pointer.class) {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode object) {
b.addPush(JavaKind.Object, new PiNode(object, nonZeroWord()));
return true;
}
});
r.register(new RequiredInvocationPlugin("readStackPointer") {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
b.addPush(JavaKind.Object, ReadReservedRegister.createReadStackPointerNode(b.getGraph()));
return true;
}
});
r.register(new RequiredInvocationPlugin("readCallerStackPointer") {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
checkNeverInline(b);
b.addPush(JavaKind.Object, new ReadCallerStackPointerNode());
return true;
}
});
r.register(new RequiredInvocationPlugin("readReturnAddress") {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
checkNeverInline(b);
b.addPush(JavaKind.Object, new ReadReturnAddressNode());
return true;
}
});
r.register(new RequiredInvocationPlugin("farReturn", Object.class, Pointer.class, CodePointer.class, boolean.class) {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode result, ValueNode sp, ValueNode ip, ValueNode fromMethodWithCalleeSavedRegisters) {
if (!fromMethodWithCalleeSavedRegisters.isConstant()) {
throw b.bailout("parameter fromMethodWithCalleeSavedRegisters is not a compile time constant for call to " + targetMethod.format("%H.%n(%p)") + " in " + b.getMethod().asStackTraceElement(b.bci()));
}
b.add(new FarReturnNode(result, sp, ip, fromMethodWithCalleeSavedRegisters.asJavaConstant().asInt() != 0));
return true;
}
});
r.register(new RequiredInvocationPlugin("testDeoptimize") {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
b.add(new TestDeoptimizeNode());
return true;
}
});
r.register(new RequiredInvocationPlugin("isDeoptimizationTarget") {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
if (SubstrateOptions.parseOnce()) {
throw VMError.unimplemented("Intrinsification of isDeoptimizationTarget not done yet");
}
if (b.getGraph().method() instanceof SharedMethod) {
SharedMethod method = (SharedMethod) b.getGraph().method();
if (method.isDeoptTarget()) {
b.addPush(JavaKind.Boolean, ConstantNode.forBoolean(true));
} else {
b.addPush(JavaKind.Boolean, ConstantNode.forBoolean(false));
}
} else {
// In analysis the value is always true.
b.addPush(JavaKind.Boolean, ConstantNode.forBoolean(true));
}
return true;
}
});
registerCastExact(r);
}
use of org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.RequiredInvocationPlugin in project graal by oracle.
the class SubstrateGraphBuilderPlugins method registerUnsafePlugins.
private static void registerUnsafePlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins, SnippetReflectionProvider snippetReflection, ParsingReason reason) {
registerUnsafePlugins(metaAccess, new Registration(plugins, sun.misc.Unsafe.class), snippetReflection, reason, true);
Registration r = new Registration(plugins, "jdk.internal.misc.Unsafe");
registerUnsafePlugins(metaAccess, r, snippetReflection, reason, false);
r.register(new RequiredInvocationPlugin("objectFieldOffset", Receiver.class, Class.class, String.class) {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode classNode, ValueNode nameNode) {
if (classNode.isConstant() && nameNode.isConstant()) {
/* If the class and field name arguments are constant. */
Class<?> clazz = snippetReflection.asObject(Class.class, classNode.asJavaConstant());
String fieldName = snippetReflection.asObject(String.class, nameNode.asJavaConstant());
try {
Field targetField = clazz.getDeclaredField(fieldName);
return processFieldOffset(b, targetField, reason, metaAccess, false);
} catch (NoSuchFieldException | LinkageError e) {
return false;
}
}
return false;
}
});
r.register(new RequiredInvocationPlugin("allocateUninitializedArray", Receiver.class, Class.class, int.class) {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver unsafe, ValueNode componentTypeNode, ValueNode lengthNode) {
/*
* For simplicity, we only intrinsify if the componentType is a compile-time
* constant. That also allows us to constant-fold the required check that the
* component type is a primitive type.
*/
if (!componentTypeNode.isJavaConstant() || componentTypeNode.asJavaConstant().isNull()) {
return false;
}
ResolvedJavaType componentType = b.getConstantReflection().asJavaType(componentTypeNode.asJavaConstant());
if (componentType == null || !componentType.isPrimitive()) {
return false;
}
/* Emits a null-check for the otherwise unused receiver. */
unsafe.get();
/*
* Note that allocateUninitializedArray must throw a IllegalArgumentException, and
* not a NegativeArraySizeException, when the length is negative.
*/
ValueNode lengthPositive = b.maybeEmitExplicitNegativeArraySizeCheck(lengthNode, BytecodeExceptionNode.BytecodeExceptionKind.ILLEGAL_ARGUMENT_EXCEPTION_NEGATIVE_LENGTH);
b.addPush(JavaKind.Object, new NewArrayNode(componentType, lengthPositive, false));
return true;
}
});
}
use of org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.RequiredInvocationPlugin in project graal by oracle.
the class ReflectionPlugins method registerFoldInvocationPlugin.
private void registerFoldInvocationPlugin(InvocationPlugins plugins, Method reflectionMethod) {
if (!ALLOWED_CONSTANT_CLASSES.contains(reflectionMethod.getReturnType()) && !reflectionMethod.getReturnType().isPrimitive()) {
throw VMError.shouldNotReachHere("Return type of method " + reflectionMethod + " is not on the allow-list for types that are immutable");
}
reflectionMethod.setAccessible(true);
List<Class<?>> parameterTypes = new ArrayList<>();
if (!Modifier.isStatic(reflectionMethod.getModifiers())) {
parameterTypes.add(Receiver.class);
}
parameterTypes.addAll(Arrays.asList(reflectionMethod.getParameterTypes()));
plugins.register(reflectionMethod.getDeclaringClass(), new RequiredInvocationPlugin(reflectionMethod.getName(), parameterTypes.toArray(new Class<?>[0])) {
@Override
public boolean defaultHandler(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode... args) {
return foldInvocationUsingReflection(b, targetMethod, reflectionMethod, receiver, args);
}
});
}
use of org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.RequiredInvocationPlugin in project graal by oracle.
the class VMThreadSTFeature method registerInvocationPlugins.
/**
* Intrinsify the {@code get()} and {@code set()} methods during bytecode parsing. We know that
* every subclass of VMThreadLocal has the same methods. Only the signatures differ based on the
* type of value.
* <p>
* The value is stored in the two arrays that are in the image heap: a Object[] array for thread
* local object variables, and a byte[] array for all thread local primitive variables.
* Therefore, we need the proper read/write barriers. The {@link IsolateThread} parameter is
* ignored.
*/
@Override
public void registerInvocationPlugins(Providers providers, SnippetReflectionProvider snippetReflection, Plugins plugins, ParsingReason reason) {
for (Class<? extends FastThreadLocal> threadLocalClass : VMThreadLocalInfo.THREAD_LOCAL_CLASSES) {
Registration r = new Registration(plugins.getInvocationPlugins(), threadLocalClass);
Class<?> valueClass = VMThreadLocalInfo.getValueClass(threadLocalClass);
registerAccessors(r, valueClass, false);
registerAccessors(r, valueClass, true);
/* compareAndSet() method without the VMThread parameter. */
r.register(new RequiredInvocationPlugin("compareAndSet", Receiver.class, valueClass, valueClass) {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode expect, ValueNode update) {
return handleCompareAndSet(b, targetMethod, receiver, expect, update);
}
});
/* get() method with the VMThread parameter. */
r.register(new RequiredInvocationPlugin("compareAndSet", Receiver.class, IsolateThread.class, valueClass, valueClass) {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode threadNode, ValueNode expect, ValueNode update) {
return handleCompareAndSet(b, targetMethod, receiver, expect, update);
}
});
}
Class<?>[] typesWithGetAddress = new Class<?>[] { FastThreadLocalBytes.class, FastThreadLocalWord.class };
for (Class<?> type : typesWithGetAddress) {
Registration r = new Registration(plugins.getInvocationPlugins(), type);
/* getAddress() method without the VMThread parameter. */
r.register(new RequiredInvocationPlugin("getAddress", Receiver.class) {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
return handleGetAddress(b, targetMethod, receiver);
}
});
/* getAddress() method with the VMThread parameter. */
r.register(new RequiredInvocationPlugin("getAddress", Receiver.class, IsolateThread.class) {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode threadNode) {
return handleGetAddress(b, targetMethod, receiver);
}
});
}
}
use of org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.RequiredInvocationPlugin in project graal by oracle.
the class VMThreadMTFeature method registerInvocationPlugins.
/**
* Intrinsify the {@code get()} and {@code set()} methods during bytecode parsing. We know that
* every subclass of VMThreadLocal has the same methods. Only the signatures differ based on the
* type of value.
* <p>
* When the {@link IsolateThread} is not passed in as a parameter, we use the
* {@link LoadVMThreadLocalNode current thread}. We do not need read/write barriers since we
* access memory that we manage ourselfs.
*/
@Override
public void registerInvocationPlugins(Providers providers, SnippetReflectionProvider snippetReflection, Plugins plugins, ParsingReason reason) {
for (Class<? extends FastThreadLocal> threadLocalClass : VMThreadLocalInfo.THREAD_LOCAL_CLASSES) {
Registration r = new Registration(plugins.getInvocationPlugins(), threadLocalClass);
Class<?> valueClass = VMThreadLocalInfo.getValueClass(threadLocalClass);
registerAccessors(r, valueClass, false);
registerAccessors(r, valueClass, true);
/* compareAndSet() method without the VMThread parameter. */
r.register(new RequiredInvocationPlugin("compareAndSet", Receiver.class, valueClass, valueClass) {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode expect, ValueNode update) {
ValueNode threadNode = currentThread(b);
return handleCompareAndSet(b, targetMethod, receiver, threadNode, expect, update);
}
});
/* get() method with the VMThread parameter. */
r.register(new RequiredInvocationPlugin("compareAndSet", Receiver.class, IsolateThread.class, valueClass, valueClass) {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode threadNode, ValueNode expect, ValueNode update) {
return handleCompareAndSet(b, targetMethod, receiver, threadNode, expect, update);
}
});
}
Class<?>[] typesWithGetAddress = new Class<?>[] { FastThreadLocalBytes.class, FastThreadLocalWord.class };
for (Class<?> type : typesWithGetAddress) {
Registration r = new Registration(plugins.getInvocationPlugins(), type);
/* getAddress() method without the VMThread parameter. */
r.register(new RequiredInvocationPlugin("getAddress", Receiver.class) {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
ValueNode threadNode = currentThread(b);
return handleGetAddress(b, targetMethod, receiver, threadNode);
}
});
/* getAddress() method with the VMThread parameter. */
r.register(new RequiredInvocationPlugin("getAddress", Receiver.class, IsolateThread.class) {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode threadNode) {
return handleGetAddress(b, targetMethod, receiver, threadNode);
}
});
}
}
Aggregations