use of org.graalvm.compiler.nodes.java.NewInstanceNode in project graal by oracle.
the class ObjectCloneNode method getLoweredSnippetGraph.
@Override
@SuppressWarnings("try")
protected StructuredGraph getLoweredSnippetGraph(LoweringTool tool) {
ResolvedJavaType type = StampTool.typeOrNull(getObject());
if (type != null) {
if (type.isArray()) {
Method method = ObjectCloneSnippets.arrayCloneMethods.get(type.getComponentType().getJavaKind());
if (method != null) {
final ResolvedJavaMethod snippetMethod = tool.getMetaAccess().lookupJavaMethod(method);
final Replacements replacements = tool.getReplacements();
StructuredGraph snippetGraph = null;
DebugContext debug = getDebug();
try (DebugContext.Scope s = debug.scope("ArrayCloneSnippet", snippetMethod)) {
snippetGraph = replacements.getSnippet(snippetMethod, null, graph().trackNodeSourcePosition(), this.getNodeSourcePosition());
} catch (Throwable e) {
throw debug.handle(e);
}
assert snippetGraph != null : "ObjectCloneSnippets should be installed";
assert getConcreteType(stamp(NodeView.DEFAULT)) != null;
return lowerReplacement((StructuredGraph) snippetGraph.copy(getDebug()), tool);
}
assert false : "unhandled array type " + type.getComponentType().getJavaKind();
} else {
Assumptions assumptions = graph().getAssumptions();
type = getConcreteType(getObject().stamp(NodeView.DEFAULT));
if (type != null) {
StructuredGraph newGraph = new StructuredGraph.Builder(graph().getOptions(), graph().getDebug(), AllowAssumptions.ifNonNull(assumptions)).build();
ParameterNode param = newGraph.addWithoutUnique(new ParameterNode(0, StampPair.createSingle(getObject().stamp(NodeView.DEFAULT))));
NewInstanceNode newInstance = newGraph.add(new NewInstanceNode(type, true));
newGraph.addAfterFixed(newGraph.start(), newInstance);
ReturnNode returnNode = newGraph.add(new ReturnNode(newInstance));
newGraph.addAfterFixed(newInstance, returnNode);
for (ResolvedJavaField field : type.getInstanceFields(true)) {
LoadFieldNode load = newGraph.add(LoadFieldNode.create(newGraph.getAssumptions(), param, field));
newGraph.addBeforeFixed(returnNode, load);
newGraph.addBeforeFixed(returnNode, newGraph.add(new StoreFieldNode(newInstance, field, load)));
}
assert getConcreteType(stamp(NodeView.DEFAULT)) != null;
return lowerReplacement(newGraph, tool);
}
}
}
assert getConcreteType(stamp(NodeView.DEFAULT)) == null;
return null;
}
use of org.graalvm.compiler.nodes.java.NewInstanceNode in project graal by oracle.
the class MethodTypeFlowBuilder method registerUsedElements.
public static void registerUsedElements(BigBang bb, StructuredGraph graph, MethodTypeFlow methodFlow) {
for (Node n : graph.getNodes()) {
if (n instanceof InstanceOfNode) {
InstanceOfNode node = (InstanceOfNode) n;
AnalysisType type = (AnalysisType) node.type().getType();
type.registerAsInTypeCheck();
} else if (n instanceof NewInstanceNode) {
NewInstanceNode node = (NewInstanceNode) n;
AnalysisType type = (AnalysisType) node.instanceClass();
type.registerAsAllocated(node);
} else if (n instanceof NewArrayNode) {
NewArrayNode node = (NewArrayNode) n;
AnalysisType type = ((AnalysisType) node.elementType()).getArrayClass();
type.registerAsAllocated(node);
} else if (n instanceof NewMultiArrayNode) {
NewMultiArrayNode node = (NewMultiArrayNode) n;
AnalysisType type = ((AnalysisType) node.type());
for (int i = 0; i < node.dimensionCount(); i++) {
type.registerAsAllocated(node);
type = type.getComponentType();
}
} else if (n instanceof BoxNode) {
BoxNode node = (BoxNode) n;
AnalysisType type = (AnalysisType) StampTool.typeOrNull(node);
type.registerAsAllocated(node);
} else if (n instanceof LoadFieldNode) {
LoadFieldNode node = (LoadFieldNode) n;
AnalysisField field = (AnalysisField) node.field();
field.registerAsRead(methodFlow);
} else if (n instanceof StoreFieldNode) {
StoreFieldNode node = (StoreFieldNode) n;
AnalysisField field = (AnalysisField) node.field();
field.registerAsWritten(methodFlow);
} else if (n instanceof StoreIndexedNode) {
StoreIndexedNode node = (StoreIndexedNode) n;
AnalysisType arrayType = (AnalysisType) StampTool.typeOrNull(node.array());
if (arrayType != null) {
assert arrayType.isArray();
arrayType.getComponentType().registerAsInTypeCheck();
}
} else if (n instanceof BytecodeExceptionNode) {
BytecodeExceptionNode node = (BytecodeExceptionNode) n;
AnalysisType type = bb.getMetaAccess().lookupJavaType(node.getExceptionClass());
type.registerAsInHeap();
} else if (n instanceof ConstantNode) {
ConstantNode cn = (ConstantNode) n;
if (cn.hasUsages() && cn.asJavaConstant().getJavaKind() == JavaKind.Object && cn.asJavaConstant().isNonNull()) {
assert StampTool.isExactType(cn);
AnalysisType type = (AnalysisType) StampTool.typeOrNull(cn);
type.registerAsInHeap();
}
} else if (n instanceof ForeignCallNode) {
ForeignCallNode node = (ForeignCallNode) n;
registerForeignCall(bb, node.getDescriptor());
} else if (n instanceof UnaryMathIntrinsicNode) {
UnaryMathIntrinsicNode node = (UnaryMathIntrinsicNode) n;
registerForeignCall(bb, node.getOperation().foreignCallDescriptor);
} else if (n instanceof BinaryMathIntrinsicNode) {
BinaryMathIntrinsicNode node = (BinaryMathIntrinsicNode) n;
registerForeignCall(bb, node.getOperation().foreignCallDescriptor);
}
}
}
use of org.graalvm.compiler.nodes.java.NewInstanceNode in project graal by oracle.
the class PEGraphDecoder method canonicalizeFixedNode.
@SuppressWarnings("try")
@Override
protected Node canonicalizeFixedNode(MethodScope s, Node node) {
PEMethodScope methodScope = (PEMethodScope) s;
Node replacedNode = node;
if (nodePlugins != null && nodePlugins.length > 0) {
if (node instanceof LoadFieldNode) {
LoadFieldNode loadFieldNode = (LoadFieldNode) node;
PEAppendGraphBuilderContext graphBuilderContext = new PEAppendGraphBuilderContext(methodScope, loadFieldNode);
ResolvedJavaField field = loadFieldNode.field();
if (loadFieldNode.isStatic()) {
for (NodePlugin nodePlugin : nodePlugins) {
if (nodePlugin.handleLoadStaticField(graphBuilderContext, field)) {
replacedNode = graphBuilderContext.pushedNode;
break;
}
}
} else {
ValueNode object = loadFieldNode.object();
for (NodePlugin nodePlugin : nodePlugins) {
if (nodePlugin.handleLoadField(graphBuilderContext, object, field)) {
replacedNode = graphBuilderContext.pushedNode;
break;
}
}
}
} else if (node instanceof StoreFieldNode) {
StoreFieldNode storeFieldNode = (StoreFieldNode) node;
PEAppendGraphBuilderContext graphBuilderContext = new PEAppendGraphBuilderContext(methodScope, storeFieldNode);
ResolvedJavaField field = storeFieldNode.field();
if (storeFieldNode.isStatic()) {
ValueNode value = storeFieldNode.value();
for (NodePlugin nodePlugin : nodePlugins) {
if (nodePlugin.handleStoreStaticField(graphBuilderContext, field, value)) {
replacedNode = graphBuilderContext.pushedNode;
break;
}
}
} else {
ValueNode object = storeFieldNode.object();
ValueNode value = storeFieldNode.value();
for (NodePlugin nodePlugin : nodePlugins) {
if (nodePlugin.handleStoreField(graphBuilderContext, object, field, value)) {
replacedNode = graphBuilderContext.pushedNode;
break;
}
}
}
} else if (node instanceof LoadIndexedNode) {
LoadIndexedNode loadIndexedNode = (LoadIndexedNode) node;
PEAppendGraphBuilderContext graphBuilderContext = new PEAppendGraphBuilderContext(methodScope, loadIndexedNode);
ValueNode array = loadIndexedNode.array();
ValueNode index = loadIndexedNode.index();
for (NodePlugin nodePlugin : nodePlugins) {
if (nodePlugin.handleLoadIndexed(graphBuilderContext, array, index, loadIndexedNode.elementKind())) {
replacedNode = graphBuilderContext.pushedNode;
break;
}
}
} else if (node instanceof StoreIndexedNode) {
StoreIndexedNode storeIndexedNode = (StoreIndexedNode) node;
PEAppendGraphBuilderContext graphBuilderContext = new PEAppendGraphBuilderContext(methodScope, storeIndexedNode);
ValueNode array = storeIndexedNode.array();
ValueNode index = storeIndexedNode.index();
ValueNode value = storeIndexedNode.value();
for (NodePlugin nodePlugin : nodePlugins) {
if (nodePlugin.handleStoreIndexed(graphBuilderContext, array, index, storeIndexedNode.elementKind(), value)) {
replacedNode = graphBuilderContext.pushedNode;
break;
}
}
} else if (node instanceof NewInstanceNode) {
NewInstanceNode newInstanceNode = (NewInstanceNode) node;
PEAppendGraphBuilderContext graphBuilderContext = new PEAppendGraphBuilderContext(methodScope, newInstanceNode);
ResolvedJavaType type = newInstanceNode.instanceClass();
for (NodePlugin nodePlugin : nodePlugins) {
if (nodePlugin.handleNewInstance(graphBuilderContext, type)) {
replacedNode = graphBuilderContext.pushedNode;
break;
}
}
} else if (node instanceof NewArrayNode) {
NewArrayNode newArrayNode = (NewArrayNode) node;
PEAppendGraphBuilderContext graphBuilderContext = new PEAppendGraphBuilderContext(methodScope, newArrayNode);
ResolvedJavaType elementType = newArrayNode.elementType();
ValueNode length = newArrayNode.length();
for (NodePlugin nodePlugin : nodePlugins) {
if (nodePlugin.handleNewArray(graphBuilderContext, elementType, length)) {
replacedNode = graphBuilderContext.pushedNode;
break;
}
}
} else if (node instanceof NewMultiArrayNode) {
NewMultiArrayNode newArrayNode = (NewMultiArrayNode) node;
PEAppendGraphBuilderContext graphBuilderContext = new PEAppendGraphBuilderContext(methodScope, newArrayNode);
ResolvedJavaType elementType = newArrayNode.type();
ValueNode[] dimensions = newArrayNode.dimensions().toArray(new ValueNode[0]);
for (NodePlugin nodePlugin : nodePlugins) {
if (nodePlugin.handleNewMultiArray(graphBuilderContext, elementType, dimensions)) {
replacedNode = graphBuilderContext.pushedNode;
break;
}
}
}
}
return super.canonicalizeFixedNode(methodScope, replacedNode);
}
use of org.graalvm.compiler.nodes.java.NewInstanceNode 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.java.NewInstanceNode in project graal by oracle.
the class CEntryPointCallStubMethod method adaptReturnValue.
private ValueNode adaptReturnValue(ResolvedJavaMethod method, HostedProviders providers, Purpose purpose, UniverseMetaAccess metaAccess, NativeLibraries nativeLibraries, HostedGraphKit kit, ValueNode invokeValue) {
ValueNode returnValue = invokeValue;
if (returnValue.getStackKind().isPrimitive()) {
return returnValue;
}
JavaType returnType = method.getSignature().getReturnType(null);
ElementInfo typeInfo = nativeLibraries.findElementInfo(returnType);
if (typeInfo instanceof EnumInfo) {
UserError.guarantee(typeInfo.getChildren().stream().anyMatch(EnumValueInfo.class::isInstance), "Enum class " + returnType.toJavaName() + " needs a method that is annotated with @" + CEnumValue.class + " because it is used as the return type of an entry point method: " + targetMethod.format("%H.%n(%p)"));
IsNullNode isNull = kit.unique(new IsNullNode(returnValue));
kit.startIf(isNull, BranchProbabilityNode.VERY_SLOW_PATH_PROBABILITY);
kit.thenPart();
ResolvedJavaType enumExceptionType = metaAccess.lookupJavaType(RuntimeException.class);
NewInstanceNode enumException = kit.append(new NewInstanceNode(enumExceptionType, true));
Iterator<ResolvedJavaMethod> enumExceptionCtor = Arrays.stream(enumExceptionType.getDeclaredConstructors()).filter(c -> c.getSignature().getParameterCount(false) == 1 && c.getSignature().getParameterType(0, null).equals(metaAccess.lookupJavaType(String.class))).iterator();
ConstantNode enumExceptionMessage = kit.createConstant(kit.getConstantReflection().forString("null return value cannot be converted to a C enum value"), JavaKind.Object);
kit.createJavaCallWithExceptionAndUnwind(InvokeKind.Special, enumExceptionCtor.next(), enumException, enumExceptionMessage);
assert !enumExceptionCtor.hasNext();
kit.append(new CEntryPointLeaveNode(LeaveAction.ExceptionAbort, enumException));
kit.append(new DeadEndNode());
kit.endIf();
// Always return enum values as a signed word because it should never be a problem if
// the caller expects a narrower integer type and the various checks already handle
// replacements with word types
CInterfaceEnumTool tool = new CInterfaceEnumTool(providers.getMetaAccess(), providers.getSnippetReflection());
JavaKind cEnumReturnType = providers.getWordTypes().getWordKind();
assert !cEnumReturnType.isUnsigned() : "requires correct representation of signed values";
returnValue = tool.createEnumValueInvoke(kit, (EnumInfo) typeInfo, cEnumReturnType, returnValue);
} else if (purpose != Purpose.ANALYSIS) {
// for analysis test cases: abort only during compilation
throw UserError.abort("Entry point method return types are restricted to primitive types, word types and enumerations (@" + CEnum.class.getSimpleName() + "): " + targetMethod.format("%H.%n(%p)"));
}
return returnValue;
}
Aggregations