use of jdk.vm.ci.meta.JavaConstant in project graal by oracle.
the class PEReadEliminationClosure method processLoadIndexed.
private boolean processLoadIndexed(LoadIndexedNode load, PEReadEliminationBlockState state, GraphEffectList effects) {
if (load.index().isConstant()) {
int index = ((JavaConstant) load.index().asConstant()).asInt();
// BALOAD (with elementKind being Byte) can be used to retrieve values from boolean
// arrays.
JavaKind elementKind = load.elementKind();
if (elementKind == JavaKind.Byte) {
elementKind = getElementKindFromStamp(load.array());
if (elementKind == JavaKind.Illegal) {
return false;
}
}
LocationIdentity arrayLocation = NamedLocationIdentity.getArrayLocation(elementKind);
return processLoad(load, load.array(), arrayLocation, index, elementKind, state, effects);
}
return false;
}
use of jdk.vm.ci.meta.JavaConstant in project graal by oracle.
the class ComputedValueField method readValue.
@Override
public JavaConstant readValue(JavaConstant receiver) {
if (constantValue != null) {
return constantValue;
}
if (kind == RecomputeFieldValue.Kind.None || kind == RecomputeFieldValue.Kind.Manual) {
return ReadableJavaField.readFieldValue(GraalAccess.getOriginalProviders().getConstantReflection(), original, receiver);
}
JavaConstant result = valueCache.get(receiver);
if (result != null) {
return result;
}
SnippetReflectionProvider originalSnippetReflection = GraalAccess.getOriginalSnippetReflection();
switch(kind) {
case ArrayBaseOffset:
constantValue = asConstant(ConfigurationValues.getObjectLayout().getArrayBaseOffset(JavaKind.fromJavaClass(targetClass.getComponentType())));
return constantValue;
case ArrayIndexScale:
constantValue = asConstant(ConfigurationValues.getObjectLayout().getArrayIndexScale(JavaKind.fromJavaClass(targetClass.getComponentType())));
return constantValue;
case ArrayIndexShift:
constantValue = asConstant(ConfigurationValues.getObjectLayout().getArrayIndexShift(JavaKind.fromJavaClass(targetClass.getComponentType())));
return constantValue;
case NewInstance:
try {
Constructor<?> constructor = targetClass.getDeclaredConstructor();
constructor.setAccessible(true);
result = originalSnippetReflection.forObject(constructor.newInstance());
} catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException ex) {
throw shouldNotReachHere("Error performing field recomputation for alias " + annotated.format("%H.%n"), ex);
}
break;
case AtomicFieldUpdaterOffset:
result = computeAtomicFieldUpdaterOffset(receiver);
break;
case TranslateFieldOffset:
result = translateFieldOffset(receiver, targetClass);
break;
case Custom:
try {
Constructor<?>[] constructors = targetClass.getDeclaredConstructors();
if (constructors.length != 1) {
throw shouldNotReachHere("The " + CustomFieldValueComputer.class.getSimpleName() + " class " + targetClass.getName() + " has more than one constructor");
}
Constructor<?> constructor = constructors[0];
Object[] constructorArgs = new Object[constructor.getParameterCount()];
for (int i = 0; i < constructorArgs.length; i++) {
constructorArgs[i] = configurationValue(constructor.getParameterTypes()[i]);
}
constructor.setAccessible(true);
CustomFieldValueComputer computer = (CustomFieldValueComputer) constructor.newInstance(constructorArgs);
Object receiverValue = receiver == null ? null : originalSnippetReflection.asObject(Object.class, receiver);
result = originalSnippetReflection.forBoxed(annotated.getJavaKind(), computer.compute(original, annotated, receiverValue));
assert result.getJavaKind() == annotated.getJavaKind();
} catch (InvocationTargetException | InstantiationException | IllegalAccessException ex) {
throw shouldNotReachHere("Error performing field recomputation for alias " + annotated.format("%H.%n"), ex);
}
break;
default:
throw shouldNotReachHere("Field recomputation of kind " + kind + " specified by alias " + annotated.format("%H.%n") + " not yet supported");
}
valueCache.put(receiver, result);
return result;
}
use of jdk.vm.ci.meta.JavaConstant in project graal by oracle.
the class IntrinsifyMethodHandlesInvocationPlugin method processInvokeWithMethodHandle.
@SuppressWarnings("try")
private void processInvokeWithMethodHandle(GraphBuilderContext b, BytecodeProvider bytecodeProvider, ResolvedJavaMethod methodHandleMethod, ValueNode[] methodHandleArguments) {
Plugins graphBuilderPlugins = new Plugins(((ReplacementsImpl) originalProviders.getReplacements()).getGraphBuilderPlugins());
registerInvocationPlugins(graphBuilderPlugins.getInvocationPlugins(), bytecodeProvider);
graphBuilderPlugins.prependParameterPlugin(new MethodHandlesParameterPlugin(methodHandleArguments));
graphBuilderPlugins.clearInlineInvokePlugins();
graphBuilderPlugins.prependInlineInvokePlugin(new MethodHandlesInlineInvokePlugin());
graphBuilderPlugins.prependNodePlugin(new MethodHandlePlugin(originalProviders.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 WordTypes(originalProviders.getMetaAccess(), FrameAccess.getWordKind()));
graphBuilderPlugins.appendInlineInvokePlugin(wordOperationPlugin);
graphBuilderPlugins.appendTypePlugin(wordOperationPlugin);
graphBuilderPlugins.appendTypePlugin(new TrustedInterfaceTypePlugin());
graphBuilderPlugins.appendNodePlugin(wordOperationPlugin);
GraphBuilderConfiguration graphBuilderConfig = GraphBuilderConfiguration.getSnippetDefault(graphBuilderPlugins);
GraphBuilderPhase.Instance graphBuilder = new GraphBuilderPhase.Instance(originalProviders.getMetaAccess(), originalProviders.getStampProvider(), originalProviders.getConstantReflection(), originalProviders.getConstantFieldProvider(), graphBuilderConfig, OptimisticOptimizations.NONE, null);
DebugContext debug = b.getDebug();
StructuredGraph graph = new StructuredGraph.Builder(b.getOptions(), debug).method(toOriginal(methodHandleMethod)).build();
try (DebugContext.Scope s = debug.scope("IntrinsifyMethodHandles", graph)) {
graphBuilder.apply(graph);
/*
* We do not care about the improved type information from Pi nodes, so we just delete
* them to simplify our graph.
*/
for (PiNode pi : graph.getNodes(PiNode.TYPE)) {
pi.replaceAndDelete(pi.object());
}
/*
* Support for MethodHandle that adapt the input type to a more generic type, i.e., a
* MethodHandle that does a dynamic type check on a parameter.
*/
for (UnaryOpLogicNode node : graph.getNodes().filter(UnaryOpLogicNode.class).filter(v -> v instanceof IsNullNode || v instanceof InstanceOfNode)) {
ValueNode value = node.getValue();
if (value instanceof ParameterNode) {
/*
* We just assume that the InstanceOfNode or IsNullNode are used in an If and
* the true-successor is actually the branch we want. If that assumption is
* wrong, nothing bad happens - we will just continue to report the invocation
* as unsupported because the updated stamp for the parameter will not simplify
* the graph.
*/
if (node instanceof InstanceOfNode) {
InstanceOfNode inst = (InstanceOfNode) node;
TypeReference typeRef = inst.type();
value.setStamp(new ObjectStamp(typeRef.getType(), typeRef.isExact(), !inst.allowsNull(), false));
} else {
assert node instanceof IsNullNode;
ResolvedJavaType type = value.stamp(NodeView.DEFAULT).javaType(originalProviders.getMetaAccess());
value.setStamp(new ObjectStamp(type, false, /* non-null */
true, false));
}
}
}
/*
* The canonicalizer converts unsafe field accesses for get/set method handles back to
* high-level field load and store nodes.
*/
new CanonicalizerPhase().apply(graph, new PhaseContext(originalProviders));
for (FixedGuardNode guard : graph.getNodes(FixedGuardNode.TYPE)) {
if (guard.next() instanceof AccessFieldNode && guard.condition() instanceof IsNullNode && guard.isNegated() && ((IsNullNode) guard.condition()).getValue() == ((AccessFieldNode) guard.next()).object()) {
/*
* Method handles to load and stores fields have null checks. Remove them, since
* the null check is implicitly done by the field access.
*/
GraphUtil.removeFixedWithUnusedInputs(guard);
}
}
debug.dump(DebugContext.VERY_DETAILED_LEVEL, graph, "Final intrinisfication graph");
/*
* After parsing (and recursive inlining during parsing), the graph must contain only
* one invocation (and therefore only one MethodCallTargetNode), plus the parameters,
* constants, start, and return nodes.
*/
Node singleFunctionality = null;
ReturnNode singleReturn = null;
for (Node node : graph.getNodes()) {
if (node == graph.start() || node instanceof ParameterNode || node instanceof ConstantNode || node instanceof FrameState) {
/* Ignore the allowed framework around the nodes we care about. */
continue;
} else if (node instanceof Invoke) {
/* We check the MethodCallTargetNode, so we can ignore the invoke. */
continue;
} else if ((node instanceof MethodCallTargetNode || node instanceof LoadFieldNode || node instanceof StoreFieldNode) && singleFunctionality == null) {
singleFunctionality = node;
continue;
} else if (node instanceof ReturnNode && singleReturn == null) {
singleReturn = (ReturnNode) node;
continue;
}
throw new UnsupportedFeatureException("Invoke with MethodHandle argument could not be reduced to at most a single call: " + methodHandleMethod.format("%H.%n(%p)"));
}
if (singleFunctionality instanceof MethodCallTargetNode) {
MethodCallTargetNode singleCallTarget = (MethodCallTargetNode) singleFunctionality;
assert singleReturn.result() == null || singleReturn.result() == singleCallTarget.invoke();
/*
* Replace the originalTarget with the replacementTarget. Note that the
* replacementTarget node belongs to a different graph than originalTarget, so we
* need to match parameter back to the original graph and allocate a new
* MethodCallTargetNode for the original graph.
*/
ValueNode[] replacedArguments = new ValueNode[singleCallTarget.arguments().size()];
for (int i = 0; i < replacedArguments.length; i++) {
replacedArguments[i] = lookup(b, methodHandleArguments, singleCallTarget.arguments().get(i));
}
b.handleReplacedInvoke(singleCallTarget.invokeKind(), lookup(singleCallTarget.targetMethod()), replacedArguments, false);
} else if (singleFunctionality instanceof LoadFieldNode) {
LoadFieldNode fieldLoad = (LoadFieldNode) singleFunctionality;
b.addPush(b.getInvokeReturnType().getJavaKind(), LoadFieldNode.create(null, lookup(b, methodHandleArguments, fieldLoad.object()), lookup(fieldLoad.field())));
} else if (singleFunctionality instanceof StoreFieldNode) {
StoreFieldNode fieldStore = (StoreFieldNode) singleFunctionality;
b.add(new StoreFieldNode(lookup(b, methodHandleArguments, fieldStore.object()), lookup(fieldStore.field()), lookup(b, methodHandleArguments, fieldStore.value())));
} else if (singleReturn.result() != null) {
/* Replace the invocation with he constant result. */
JavaConstant constantResult = singleReturn.result().asJavaConstant();
assert b.getInvokeReturnType().getJavaKind() == constantResult.getJavaKind();
b.addPush(constantResult.getJavaKind(), ConstantNode.forConstant(lookup(constantResult), universeProviders.getMetaAccess()));
} else {
/* No invoke and no return value, so nothing to do. */
assert b.getInvokeReturnType().getJavaKind() == JavaKind.Void;
}
} catch (Throwable ex) {
throw debug.handle(ex);
}
}
use of jdk.vm.ci.meta.JavaConstant in project graal by oracle.
the class JNINativeCallWrapperMethod method buildGraph.
@Override
public StructuredGraph buildGraph(DebugContext debug, ResolvedJavaMethod method, HostedProviders providers, Purpose purpose) {
JNIGraphKit kit = new JNIGraphKit(debug, providers, method);
StructuredGraph graph = kit.getGraph();
InvokeWithExceptionNode handleFrame = kit.nativeCallPrologue();
ValueNode callAddress = kit.nativeCallAddress(kit.createObject(linkage));
ValueNode environment = kit.environment();
JavaType javaReturnType = method.getSignature().getReturnType(null);
JavaType[] javaArgumentTypes = method.toParameterTypes();
List<ValueNode> javaArguments = kit.loadArguments(javaArgumentTypes);
List<ValueNode> jniArguments = new ArrayList<>(2 + javaArguments.size());
List<JavaType> jniArgumentTypes = new ArrayList<>(jniArguments.size());
JavaType environmentType = providers.getMetaAccess().lookupJavaType(JNIEnvironment.class);
JavaType objectHandleType = providers.getMetaAccess().lookupJavaType(JNIObjectHandle.class);
jniArguments.add(environment);
jniArgumentTypes.add(environmentType);
if (method.isStatic()) {
JavaConstant clazz = providers.getConstantReflection().asJavaClass(method.getDeclaringClass());
ConstantNode clazzNode = ConstantNode.forConstant(clazz, providers.getMetaAccess(), graph);
ValueNode box = kit.boxObjectInLocalHandle(clazzNode);
jniArguments.add(box);
jniArgumentTypes.add(objectHandleType);
}
for (int i = 0; i < javaArguments.size(); i++) {
ValueNode arg = javaArguments.get(i);
JavaType argType = javaArgumentTypes[i];
if (javaArgumentTypes[i].getJavaKind().isObject()) {
ValueNode obj = javaArguments.get(i);
arg = kit.boxObjectInLocalHandle(obj);
argType = objectHandleType;
}
jniArguments.add(arg);
jniArgumentTypes.add(argType);
}
assert jniArguments.size() == jniArgumentTypes.size();
JavaType jniReturnType = javaReturnType;
if (jniReturnType.getJavaKind().isObject()) {
jniReturnType = objectHandleType;
}
if (getOriginal().isSynchronized()) {
ValueNode monitorObject;
if (method.isStatic()) {
Constant hubConstant = providers.getConstantReflection().asObjectHub(method.getDeclaringClass());
DynamicHub hub = (DynamicHub) SubstrateObjectConstant.asObject(hubConstant);
monitorObject = ConstantNode.forConstant(SubstrateObjectConstant.forObject(hub), providers.getMetaAccess(), graph);
} else {
monitorObject = javaArguments.get(0);
}
MonitorIdNode monitorId = graph.add(new MonitorIdNode(kit.getFrameState().lockDepth(false)));
MonitorEnterNode monitorEnter = kit.append(new MonitorEnterNode(monitorObject, monitorId));
kit.getFrameState().pushLock(monitorEnter.object(), monitorEnter.getMonitorId());
monitorEnter.setStateAfter(kit.getFrameState().create(kit.bci(), monitorEnter));
}
kit.getFrameState().clearLocals();
Signature jniSignature = new JNISignature(jniArgumentTypes, jniReturnType);
ValueNode returnValue = kit.createCFunctionCall(callAddress, method, jniArguments, jniSignature, true, false);
if (getOriginal().isSynchronized()) {
MonitorIdNode monitorId = kit.getFrameState().peekMonitorId();
ValueNode monitorObject = kit.getFrameState().popLock();
MonitorExitNode monitorExit = kit.append(new MonitorExitNode(monitorObject, monitorId, null));
monitorExit.setStateAfter(kit.getFrameState().create(kit.bci(), monitorExit));
}
if (javaReturnType.getJavaKind().isObject()) {
// before destroying handles in epilogue
returnValue = kit.unboxHandle(returnValue);
}
kit.nativeCallEpilogue(handleFrame);
kit.rethrowPendingException();
if (javaReturnType.getJavaKind().isObject()) {
// Just before return to always run the epilogue and never suppress a pending exception
returnValue = castObject(kit, returnValue, (ResolvedJavaType) javaReturnType);
}
kit.createReturn(returnValue, javaReturnType.getJavaKind());
kit.mergeUnwinds();
assert graph.verify();
return graph;
}
use of jdk.vm.ci.meta.JavaConstant in project graal by oracle.
the class ScalaAnalysisPlugin method handleInvoke.
@Override
public boolean handleInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) {
/* ClassTag(<type>.class) */
if (method.getDeclaringClass().getName().equals("Lscala/reflect/ClassTag$;") && method.getName().equals("apply") && args.length == 2) {
JavaConstant clazzConstant = args[1].asJavaConstant();
if (clazzConstant != null) {
AnalysisType type = (AnalysisType) b.getConstantReflection().asJavaType(clazzConstant);
for (int i = 0; i < SUPPORTED_LEVEL_OF_NESTED_ARRAYS; i++) {
type = type.getArrayClass();
type.registerAsInHeap();
}
}
}
return false;
}
Aggregations