use of com.oracle.graal.pointsto.flow.context.BytecodeLocation in project graal by oracle.
the class MethodTypeFlowBuilder method processNewArray.
protected void processNewArray(NewArrayNode node, TypeFlowsOfNodes state) {
AnalysisType type = ((AnalysisType) node.elementType()).getArrayClass();
assert type.isInstantiated();
Object key = uniqueKey(node);
BytecodeLocation allocationLabel = bb.analysisPolicy().createAllocationSite(bb, key, method);
TypeFlowBuilder<?> newArrayBuilder = TypeFlowBuilder.create(bb, node, NewInstanceTypeFlow.class, () -> {
NewInstanceTypeFlow newArray = createNewArrayTypeFlow(node, type, allocationLabel);
methodFlow.addAllocation(newArray);
return newArray;
});
state.add(node, newArrayBuilder);
}
use of com.oracle.graal.pointsto.flow.context.BytecodeLocation in project graal by oracle.
the class BytecodeAnalysisContext method toString.
@Override
public String toString() {
StringBuilder result = new StringBuilder();
String separator = " ";
for (BytecodeLocation bytecode : labels) {
result.append(separator).append(bytecode);
separator = "\t";
}
return result.toString();
}
use of com.oracle.graal.pointsto.flow.context.BytecodeLocation in project graal by oracle.
the class BytecodeAnalysisContextPolicy method calleeContext.
/**
* Captures the context of a method invocation.
* <p>
* Iterates over the list of {@linkplain BytecodeAnalysisContext context chains} of the receiver
* object, i.e. the contexts from which it's allocator method was invoked, and extends each of
* this chains with the current receiver's {@linkplain AnalysisObject analysis object}. The
* depth of each context chain is bounded to {@link PointstoOptions#MaxCallingContextDepth}.
* <p>
*
* @param bb the bigbang.
* @param receiverObject invocation's {@linkplain AnalysisObject receiver object}
* @return the list of {@link BytecodeAnalysisContext context chains} leading to this invocation
* extended with the current receiver object
*/
@Override
public BytecodeAnalysisContext calleeContext(BigBang bb, AnalysisObject receiverObject, BytecodeAnalysisContext callerContext, MethodTypeFlow callee) {
int maxCalleeContextDepth = callee.getLocalCallingContextDepth();
/*
* If the calling context depth is 0 return ContextChain.EMPTY_CONTEXT so that the unique
* clone is linked in.
*/
if (maxCalleeContextDepth == 0 || !receiverObject.isAllocationContextSensitiveObject()) {
return emptyContext();
}
AllocationContextSensitiveObject receiverHeapObject = (AllocationContextSensitiveObject) receiverObject;
/*
* If the context depth is greater than 0 and the receiver object has context information
* then extend the receiver's context by appending the receiver object allocation site,
* otherwise create a context containing the receiver object allocation site.
*/
BytecodeLocation[] labelList;
if (receiverHeapObject.allocationContext() != null) {
labelList = extend(((BytecodeAnalysisContext) receiverHeapObject.allocationContext()).labels(), receiverHeapObject.allocationLabel(), maxCalleeContextDepth);
} else {
// TODO remove branch if never taken
JVMCIError.shouldNotReachHere("CoreAnalysisContextPolicy.merge: receiverHeapObject.heapContext() is null");
labelList = new BytecodeLocation[] { receiverHeapObject.allocationLabel() };
}
return lookupContext(labelList);
}
use of com.oracle.graal.pointsto.flow.context.BytecodeLocation in project graal by oracle.
the class MethodTypeFlowBuilder method processNewInstance.
protected void processNewInstance(NewInstanceNode node, TypeFlowsOfNodes state) {
AnalysisType type = (AnalysisType) node.instanceClass();
assert type.isInstantiated();
Object key = uniqueKey(node);
BytecodeLocation allocationLabel = bb.analysisPolicy().createAllocationSite(bb, key, method);
TypeFlowBuilder<?> newInstanceBuilder = TypeFlowBuilder.create(bb, node, NewInstanceTypeFlow.class, () -> {
NewInstanceTypeFlow newInstance = createNewInstanceTypeFlow(node, type, allocationLabel);
/* Instance fields of a new object are initialized to null state in AnalysisField. */
methodFlow.addAllocation(newInstance);
return newInstance;
});
state.add(node, newInstanceBuilder);
}
use of com.oracle.graal.pointsto.flow.context.BytecodeLocation in project graal by oracle.
the class MethodTypeFlowBuilder method apply.
protected void apply() {
// assert method.getAnnotation(Fold.class) == null : method;
if (method.getAnnotation(NodeIntrinsic.class) != null) {
graph.getDebug().log("apply MethodTypeFlow on node intrinsic %s", method);
AnalysisType returnType = (AnalysisType) method.getSignature().getReturnType(method.getDeclaringClass());
if (returnType.getJavaKind() == JavaKind.Object) {
/*
* This is a method used in a snippet, so most likely the return value does not
* matter at all. However, some methods return an object, and the snippet continues
* to work with the object. So pretend that this method returns an object of the
* exact return type.
*/
TypeFlow<?> returnTypeFlow = methodFlow.getResultFlow().getDeclaredType().getTypeFlow(this.bb, true);
returnTypeFlow = new ProxyTypeFlow(null, returnTypeFlow);
FormalReturnTypeFlow resultFlow = new FormalReturnTypeFlow(null, returnType, method);
returnTypeFlow.addOriginalUse(this.bb, resultFlow);
methodFlow.addMiscEntry(returnTypeFlow);
methodFlow.setResult(resultFlow);
}
return;
}
if (!parse()) {
return;
}
this.bb.getUnsupportedFeatures().checkMethod(method, graph);
processedNodes = new NodeBitMap(graph);
TypeFlowsOfNodes typeFlows = new TypeFlowsOfNodes();
for (Node n : graph.getNodes()) {
if (n instanceof ParameterNode) {
ParameterNode node = (ParameterNode) n;
if (node.getStackKind() == JavaKind.Object) {
TypeFlowBuilder<?> paramBuilder = TypeFlowBuilder.create(bb, node, FormalParamTypeFlow.class, () -> {
boolean isStatic = Modifier.isStatic(method.getModifiers());
int index = node.index();
FormalParamTypeFlow parameter;
if (!isStatic && index == 0) {
AnalysisType paramType = method.getDeclaringClass();
parameter = new FormalReceiverTypeFlow(node, paramType, method);
} else {
int offset = isStatic ? 0 : 1;
AnalysisType paramType = (AnalysisType) method.getSignature().getParameterType(index - offset, method.getDeclaringClass());
parameter = new FormalParamTypeFlow(node, paramType, method, index);
}
methodFlow.setParameter(index, parameter);
return parameter;
});
typeFlowGraphBuilder.checkFormalParameterBuilder(paramBuilder);
typeFlows.add(node, paramBuilder);
}
} else if (n instanceof BoxNode) {
BoxNode node = (BoxNode) n;
Object key = uniqueKey(node);
BytecodeLocation boxSite = bb.analysisPolicy().createAllocationSite(bb, key, methodFlow.getMethod());
AnalysisType type = (AnalysisType) StampTool.typeOrNull(node);
TypeFlowBuilder<?> boxBuilder = TypeFlowBuilder.create(bb, node, BoxTypeFlow.class, () -> {
BoxTypeFlow boxFlow = new BoxTypeFlow(node, type, boxSite);
methodFlow.addAllocation(boxFlow);
return boxFlow;
});
typeFlows.add(node, boxBuilder);
}
for (Node input : n.inputs()) {
/*
* TODO change the handling of constants so that the SourceTypeFlow is created on
* demand, with the optimization that only one SourceTypeFlow is created ever for
* every distinct object (using, e.g., caching in a global IdentityHashMap).
*/
if (input instanceof ConstantNode && !typeFlows.contains((ConstantNode) input)) {
ConstantNode node = (ConstantNode) input;
if (node.asJavaConstant().isNull()) {
TypeFlowBuilder<SourceTypeFlow> sourceBuilder = TypeFlowBuilder.create(bb, node, SourceTypeFlow.class, () -> {
SourceTypeFlow constantSource = new SourceTypeFlow(node, TypeState.forNull());
methodFlow.addSource(constantSource);
return constantSource;
});
typeFlows.add(node, sourceBuilder);
} else if (node.asJavaConstant().getJavaKind() == JavaKind.Object) {
/*
* TODO a SubstrateObjectConstant wrapping a PrimitiveConstant has kind
* equals to Object. Do we care about the effective value of these primitive
* constants in the analysis?
*/
assert StampTool.isExactType(node);
AnalysisType type = (AnalysisType) StampTool.typeOrNull(node);
assert type.isInstantiated();
TypeFlowBuilder<SourceTypeFlow> sourceBuilder = TypeFlowBuilder.create(bb, node, SourceTypeFlow.class, () -> {
SourceTypeFlow constantSource = new SourceTypeFlow(node, TypeState.forConstant(this.bb, node.asJavaConstant(), type));
methodFlow.addSource(constantSource);
return constantSource;
});
typeFlows.add(node, sourceBuilder);
}
}
}
}
// Propagate the type flows through the method's graph
new NodeIterator(graph.start(), typeFlows).apply();
/* Prune the method graph. Eliminate nodes with no uses. */
typeFlowGraphBuilder.build();
/*
* Make sure that all existing InstanceOfNodes are registered even when only used as an
* input of a conditional.
*/
for (Node n : graph.getNodes()) {
if (n instanceof InstanceOfNode) {
InstanceOfNode instanceOf = (InstanceOfNode) n;
markFieldsUsedInComparison(instanceOf.getValue());
} else if (n instanceof ObjectEqualsNode) {
ObjectEqualsNode compareNode = (ObjectEqualsNode) n;
markFieldsUsedInComparison(compareNode.getX());
markFieldsUsedInComparison(compareNode.getY());
}
}
}
Aggregations