use of org.graalvm.compiler.nodes.ConstantNode in project graal by oracle.
the class AheadOfTimeCompilationTest method testBoxedBoolean.
@Test
public void testBoxedBoolean() {
StructuredGraph result = compile("getBoxedBoolean", false);
assertDeepEquals(0, result.getNodes().filter(FloatingReadNode.class).count());
assertDeepEquals(0, result.getNodes(PiNode.TYPE).count());
assertDeepEquals(1, getConstantNodes(result).count());
ConstantNode constant = getConstantNodes(result).first();
assertDeepEquals(JavaKind.Object, constant.getStackKind());
JavaConstant c = constant.asJavaConstant();
Assert.assertEquals(getSnippetReflection().asObject(Boolean.class, c), Boolean.TRUE);
}
use of org.graalvm.compiler.nodes.ConstantNode in project graal by oracle.
the class AMD64HotSpotAddressLowering method tryOptimize.
private static void tryOptimize(OffsetAddressNode offsetAddress, LoopEx loop) {
EconomicMap<Node, InductionVariable> ivs = loop.getInductionVariables();
InductionVariable currentIV = ivs.get(offsetAddress.getOffset());
while (currentIV != null) {
if (!(currentIV instanceof DerivedInductionVariable)) {
break;
}
ValueNode currentValue = currentIV.valueNode();
if (currentValue.isDeleted()) {
break;
}
if (currentValue instanceof ZeroExtendNode) {
ZeroExtendNode zeroExtendNode = (ZeroExtendNode) currentValue;
if (applicableToImplicitZeroExtend(zeroExtendNode)) {
ValueNode input = zeroExtendNode.getValue();
if (input instanceof AddNode) {
AddNode add = (AddNode) input;
if (add.getX().isConstant()) {
optimizeAdd(zeroExtendNode, (ConstantNode) add.getX(), add.getY(), loop);
} else if (add.getY().isConstant()) {
optimizeAdd(zeroExtendNode, (ConstantNode) add.getY(), add.getX(), loop);
}
}
}
}
currentIV = ((DerivedInductionVariable) currentIV).getBase();
}
}
use of org.graalvm.compiler.nodes.ConstantNode 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 org.graalvm.compiler.nodes.ConstantNode in project graal by oracle.
the class JNIJavaCallWrapperMethod method loadAndUnboxArguments.
private List<Pair<ValueNode, ResolvedJavaType>> loadAndUnboxArguments(JNIGraphKit kit, HostedProviders providers, ResolvedJavaMethod invokeMethod, Signature invokeSignature) {
MetaAccessProvider metaAccess = providers.getMetaAccess();
List<Pair<ValueNode, ResolvedJavaType>> args = new ArrayList<>();
int javaIndex = 0;
javaIndex += metaAccess.lookupJavaType(JNIEnvironment.class).getJavaKind().getSlotCount();
if (!invokeMethod.isStatic()) {
JavaKind kind = metaAccess.lookupJavaType(JNIObjectHandle.class).getJavaKind();
ValueNode handle = kit.loadLocal(javaIndex, kind);
ValueNode unboxed = kit.unboxHandle(handle);
ValueNode receiver;
ResolvedJavaType receiverClass = invokeMethod.getDeclaringClass();
if (invokeMethod.isConstructor()) {
/*
* Our target method is a constructor and we might be called via `NewObject`, in
* which case we need to allocate the object before calling the constructor. We can
* detect when this is the case because unlike with `Call<Type>Method`, we are
* passed the object hub of our target class in place of the receiver object.
*/
Constant hub = providers.getConstantReflection().asObjectHub(receiverClass);
ConstantNode hubNode = kit.createConstant(hub, JavaKind.Object);
kit.startIf(kit.unique(new ObjectEqualsNode(unboxed, hubNode)), BranchProbabilityNode.FAST_PATH_PROBABILITY);
kit.thenPart();
ValueNode created = kit.append(new NewInstanceNode(receiverClass, true));
AbstractMergeNode merge = kit.endIf();
receiver = kit.unique(new ValuePhiNode(StampFactory.object(), merge, new ValueNode[] { created, unboxed }));
} else {
receiver = unboxed;
}
args.add(Pair.create(receiver, receiverClass));
}
javaIndex += metaAccess.lookupJavaType(JNIObjectHandle.class).getJavaKind().getSlotCount();
if (nonVirtual) {
javaIndex += metaAccess.lookupJavaType(JNIObjectHandle.class).getJavaKind().getSlotCount();
}
javaIndex += metaAccess.lookupJavaType(JNIMethodId.class).getJavaKind().getSlotCount();
int count = invokeSignature.getParameterCount(false);
if (callVariant == CallVariant.VARARGS) {
for (int i = 0; i < count; i++) {
ResolvedJavaType type = (ResolvedJavaType) invokeSignature.getParameterType(i, null);
JavaKind kind = type.getJavaKind();
JavaKind loadKind = kind;
if (loadKind == JavaKind.Float) {
// C varargs promote float to double
loadKind = JavaKind.Double;
}
ValueNode value = kit.loadLocal(javaIndex, loadKind);
if (kind == JavaKind.Float) {
value = kit.unique(new FloatConvertNode(FloatConvert.D2F, value));
} else if (kind.isObject()) {
value = kit.unboxHandle(value);
}
args.add(Pair.create(value, type));
javaIndex += loadKind.getSlotCount();
}
} else if (callVariant == CallVariant.ARRAY) {
ResolvedJavaType elementType = metaAccess.lookupJavaType(JNIValue.class);
int elementSize = SizeOf.get(JNIValue.class);
ValueNode array = kit.loadLocal(javaIndex, elementType.getJavaKind());
for (int i = 0; i < count; i++) {
ResolvedJavaType type = (ResolvedJavaType) invokeSignature.getParameterType(i, null);
JavaKind readKind = type.getJavaKind();
StructFieldInfo fieldInfo = getJNIValueOffsetOf(elementType, readKind);
int offset = i * elementSize + fieldInfo.getOffsetInfo().getProperty();
ConstantNode offsetConstant = kit.createConstant(JavaConstant.forInt(offset), providers.getWordTypes().getWordKind());
OffsetAddressNode address = kit.unique(new OffsetAddressNode(array, offsetConstant));
LocationIdentity locationIdentity = fieldInfo.getLocationIdentity();
if (locationIdentity == null) {
locationIdentity = LocationIdentity.any();
}
Stamp readStamp = getNarrowStamp(providers, readKind);
ValueNode value = kit.append(new CInterfaceReadNode(address, locationIdentity, readStamp, BarrierType.NONE, "args[" + i + "]"));
JavaKind stackKind = readKind.getStackKind();
if (readKind != stackKind) {
assert stackKind.getBitCount() > readKind.getBitCount() : "read kind must be narrower than stack kind";
if (readKind.isUnsigned()) {
// needed or another op may illegally sign-extend
value = kit.unique(new ZeroExtendNode(value, stackKind.getBitCount()));
} else {
value = kit.unique(new SignExtendNode(value, stackKind.getBitCount()));
}
} else if (readKind.isObject()) {
value = kit.unboxHandle(value);
}
args.add(Pair.create(value, type));
}
} else if (callVariant == CallVariant.VA_LIST) {
ValueNode valist = kit.loadLocal(javaIndex, metaAccess.lookupJavaType(WordBase.class).getJavaKind());
for (int i = 0; i < count; i++) {
ResolvedJavaType type = (ResolvedJavaType) invokeSignature.getParameterType(i, null);
JavaKind loadKind = type.getJavaKind();
if (loadKind.isObject()) {
loadKind = providers.getWordTypes().getWordKind();
}
ValueNode value = kit.append(new VaListNextArgNode(loadKind, valist));
if (type.getJavaKind().isObject()) {
value = kit.unboxHandle(value);
}
args.add(Pair.create(value, type));
}
} else {
throw VMError.unsupportedFeature("Call variant: " + callVariant);
}
return args;
}
use of org.graalvm.compiler.nodes.ConstantNode in project graal by oracle.
the class JNIJavaCallWrapperMethod method buildGraph.
@Override
public StructuredGraph buildGraph(DebugContext debug, ResolvedJavaMethod method, HostedProviders providers, Purpose purpose) {
UniverseMetaAccess metaAccess = (UniverseMetaAccess) providers.getMetaAccess();
JNIGraphKit kit = new JNIGraphKit(debug, providers, method);
StructuredGraph graph = kit.getGraph();
FrameStateBuilder state = new FrameStateBuilder(null, method, graph);
state.initializeForMethodStart(null, true, providers.getGraphBuilderPlugins());
JavaKind vmThreadKind = metaAccess.lookupJavaType(JNIEnvironment.class).getJavaKind();
ValueNode vmThread = kit.loadLocal(0, vmThreadKind);
kit.append(new CEntryPointEnterNode(EnterAction.Enter, vmThread));
ResolvedJavaMethod invokeMethod = providers.getMetaAccess().lookupJavaMethod(reflectMethod);
Signature invokeSignature = invokeMethod.getSignature();
List<Pair<ValueNode, ResolvedJavaType>> argsWithTypes = loadAndUnboxArguments(kit, providers, invokeMethod, invokeSignature);
JavaKind returnKind = invokeSignature.getReturnKind();
if (invokeMethod.isConstructor()) {
// return `this` to implement NewObject
assert returnKind == JavaKind.Void;
returnKind = JavaKind.Object;
}
IfNode ifNode = kit.startIf(null, BranchProbabilityNode.FAST_PATH_PROBABILITY);
kit.thenPart();
LogicNode typeChecks = LogicConstantNode.tautology(kit.getGraph());
ValueNode[] args = new ValueNode[argsWithTypes.size()];
for (int i = 0; i < argsWithTypes.size(); i++) {
ValueNode value = argsWithTypes.get(i).getLeft();
ResolvedJavaType type = argsWithTypes.get(i).getRight();
if (!type.isPrimitive() && !type.isJavaLangObject()) {
TypeReference typeRef = TypeReference.createTrusted(kit.getAssumptions(), type);
LogicNode instanceOf = kit.unique(InstanceOfNode.createAllowNull(typeRef, value, null, null));
typeChecks = LogicNode.and(typeChecks, instanceOf, BranchProbabilityNode.FAST_PATH_PROBABILITY);
FixedGuardNode guard = kit.append(new FixedGuardNode(instanceOf, DeoptimizationReason.ClassCastException, DeoptimizationAction.None, false));
value = kit.append(PiNode.create(value, StampFactory.object(typeRef), guard));
}
args[i] = value;
}
// safe because logic nodes are floating
ifNode.setCondition(typeChecks);
InvokeKind kind = //
invokeMethod.isStatic() ? //
InvokeKind.Static : ((nonVirtual || invokeMethod.isConstructor()) ? InvokeKind.Special : InvokeKind.Virtual);
ValueNode invokeResult = createInvoke(kit, invokeMethod, kind, state, kit.bci(), args);
if (invokeMethod.isConstructor()) {
// return `this` to implement NewObject
invokeResult = args[0];
}
// illegal parameter types
kit.elsePart();
ConstantNode exceptionObject = kit.createObject(cachedArgumentClassCastException);
kit.retainPendingException(exceptionObject);
ValueNode typeMismatchValue = null;
if (returnKind != JavaKind.Void) {
typeMismatchValue = kit.unique(ConstantNode.defaultForKind(returnKind.getStackKind()));
}
AbstractMergeNode merge = kit.endIf();
ValueNode returnValue = null;
if (returnKind != JavaKind.Void) {
ValueNode[] inputs = { invokeResult, typeMismatchValue };
returnValue = kit.getGraph().addWithoutUnique(new ValuePhiNode(invokeResult.stamp(NodeView.DEFAULT), merge, inputs));
state.push(returnKind, returnValue);
}
merge.setStateAfter(state.create(kit.bci(), merge));
if (returnKind != JavaKind.Void) {
state.pop(returnKind);
if (returnKind.isObject()) {
returnValue = kit.boxObjectInLocalHandle(returnValue);
}
}
kit.append(new CEntryPointLeaveNode(LeaveAction.Leave));
kit.createReturn(returnValue, returnKind);
assert graph.verify();
return graph;
}
Aggregations