use of jdk.vm.ci.meta.JavaTypeProfile in project graal by oracle.
the class StaticAnalysisResultsBuilder method cachedTypeProfile.
private JavaTypeProfile cachedTypeProfile(JavaTypeProfile[] cache, int cacheIdx, TypeState typeState) {
JavaTypeProfile result = cache[cacheIdx];
if (result == null) {
result = createTypeProfile(typeState);
cache[cacheIdx] = result;
}
return result;
}
use of jdk.vm.ci.meta.JavaTypeProfile in project graal by oracle.
the class BytecodeParser method adjustProfileForInvocationPlugin.
/**
* Adjusts the profile for an indirect invocation of a virtual method for which there is an
* intrinsic. The adjustment made by this method is to remove all types from the profile that do
* not override {@code targetMethod}.
*
* @param profile the profile to adjust
* @param targetMethod the virtual method for which there is an intrinsic
* @return the adjusted profile or the original {@code profile} object if no adjustment was made
*/
protected JavaTypeProfile adjustProfileForInvocationPlugin(JavaTypeProfile profile, ResolvedJavaMethod targetMethod) {
if (profile.getTypes().length > 0) {
List<ProfiledType> retained = new ArrayList<>();
double notRecordedProbability = profile.getNotRecordedProbability();
for (ProfiledType ptype : profile.getTypes()) {
if (!ptype.getType().resolveMethod(targetMethod, method.getDeclaringClass()).equals(targetMethod)) {
retained.add(ptype);
} else {
notRecordedProbability += ptype.getProbability();
}
}
if (!retained.isEmpty()) {
if (retained.size() != profile.getTypes().length) {
return new JavaTypeProfile(profile.getNullSeen(), notRecordedProbability, retained.toArray(new ProfiledType[retained.size()]));
}
} else {
return new JavaTypeProfile(profile.getNullSeen(), notRecordedProbability, new ProfiledType[0]);
}
}
return profile;
}
use of jdk.vm.ci.meta.JavaTypeProfile in project graal by oracle.
the class AssertTypeStateNode method alwaysHolds.
@Override
protected boolean alwaysHolds(boolean reportError) {
if (getInput().isConstant()) {
if (getInput().asJavaConstant().isNull()) {
if (typeState.getNullSeen() == TriState.FALSE) {
if (reportError) {
throw shouldNotReachHere("Null constant not compatible with type state: " + this + " : " + getTypeState());
}
} else {
return true;
}
} else {
Set<ResolvedJavaType> ourTypes = new HashSet<>();
addAllTypes(ourTypes, typeState);
if (!ourTypes.contains(StampTool.typeOrNull(getInput()))) {
if (reportError) {
throw shouldNotReachHere("Constant object not compatible with type state: " + this + " : " + getTypeState() + ", " + StampTool.typeOrNull(getInput()));
}
} else {
return true;
}
}
}
if (getInput() instanceof AssertTypeStateNode) {
JavaTypeProfile inputTypeState = ((AssertTypeStateNode) getInput()).getTypeState();
Set<ResolvedJavaType> inputTypes = new HashSet<>();
addAllTypes(inputTypes, inputTypeState);
Set<ResolvedJavaType> ourTypes = new HashSet<>();
addAllTypes(ourTypes, typeState);
if (ourTypes.containsAll(inputTypes)) {
/* Another node is already checking the same or a stronger type state. */
return true;
}
}
return false;
}
use of jdk.vm.ci.meta.JavaTypeProfile in project graal by oracle.
the class BytecodeParser method guardIntrinsic.
/**
* Weaves a test of the receiver type to ensure the dispatch will select {@code targetMethod}
* and not another method that overrides it. This should only be called if there is an intrinsic
* (i.e., an {@link InvocationPlugin}) for {@code targetMethod} and the invocation is indirect.
*
* The control flow woven around the intrinsic is as follows:
*
* <pre>
* if (LoadMethod(LoadHub(receiver)) == targetMethod) {
* <intrinsic for targetMethod>
* } else {
* <virtual call to targetMethod>
* }
* </pre>
*
* The {@code else} branch is woven by {@link #afterInvocationPluginExecution}.
*
* @return {@code null} if the intrinsic cannot be used otherwise an object to be used by
* {@link #afterInvocationPluginExecution} to weave code for the non-intrinsic branch
*/
protected IntrinsicGuard guardIntrinsic(ValueNode[] args, ResolvedJavaMethod targetMethod, InvocationPluginReceiver pluginReceiver) {
ValueNode intrinsicReceiver = args[0];
ResolvedJavaType receiverType = StampTool.typeOrNull(intrinsicReceiver);
if (receiverType == null) {
// The verifier guarantees it to be at least type declaring targetMethod
receiverType = targetMethod.getDeclaringClass();
}
ResolvedJavaMethod resolvedMethod = receiverType.resolveMethod(targetMethod, method.getDeclaringClass());
if (resolvedMethod == null || resolvedMethod.equals(targetMethod)) {
assert resolvedMethod == null || targetMethod.getDeclaringClass().isAssignableFrom(resolvedMethod.getDeclaringClass());
Mark mark = graph.getMark();
FixedWithNextNode currentLastInstr = lastInstr;
ValueNode nonNullReceiver = pluginReceiver.get();
Stamp methodStamp = stampProvider.createMethodStamp();
LoadHubNode hub = graph.unique(new LoadHubNode(stampProvider, nonNullReceiver));
LoadMethodNode actual = append(new LoadMethodNode(methodStamp, targetMethod, receiverType, method.getDeclaringClass(), hub));
ConstantNode expected = graph.unique(ConstantNode.forConstant(methodStamp, targetMethod.getEncoding(), getMetaAccess()));
LogicNode compare = graph.addOrUniqueWithInputs(CompareNode.createCompareNode(constantReflection, metaAccess, options, null, CanonicalCondition.EQ, actual, expected, NodeView.DEFAULT));
JavaTypeProfile profile = null;
if (profilingInfo != null && this.optimisticOpts.useTypeCheckHints(getOptions())) {
profile = profilingInfo.getTypeProfile(bci());
if (profile != null) {
JavaTypeProfile newProfile = adjustProfileForInvocationPlugin(profile, targetMethod);
if (newProfile != profile) {
if (newProfile.getTypes().length == 0) {
// All profiled types select the intrinsic so
// emit a fixed guard instead of an if-then-else.
lastInstr = append(new FixedGuardNode(compare, TypeCheckedInliningViolated, InvalidateReprofile, false));
return new IntrinsicGuard(currentLastInstr, intrinsicReceiver, mark, null, null);
}
} else {
// No profiled types select the intrinsic so emit a virtual call
return null;
}
profile = newProfile;
}
}
AbstractBeginNode intrinsicBranch = graph.add(new BeginNode());
AbstractBeginNode nonIntrinsicBranch = graph.add(new BeginNode());
append(new IfNode(compare, intrinsicBranch, nonIntrinsicBranch, FAST_PATH_PROBABILITY));
lastInstr = intrinsicBranch;
return new IntrinsicGuard(currentLastInstr, intrinsicReceiver, mark, nonIntrinsicBranch, profile);
} else {
// Receiver selects an overriding method so emit a virtual call
return null;
}
}
use of jdk.vm.ci.meta.JavaTypeProfile in project graal by oracle.
the class BytecodeParser method genInstanceOf.
private void genInstanceOf() {
int cpi = getStream().readCPI();
JavaType type = lookupType(cpi, INSTANCEOF);
ValueNode object = frameState.pop(JavaKind.Object);
if (!(type instanceof ResolvedJavaType)) {
handleUnresolvedInstanceOf(type, object);
return;
}
TypeReference resolvedType = TypeReference.createTrusted(graph.getAssumptions(), (ResolvedJavaType) type);
JavaTypeProfile profile = getProfileForTypeCheck(resolvedType);
for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) {
if (plugin.handleInstanceOf(this, object, resolvedType.getType(), profile)) {
return;
}
}
LogicNode instanceOfNode = null;
if (profile != null) {
if (profile.getNullSeen().isFalse()) {
object = nullCheckedValue(object);
ResolvedJavaType singleType = profile.asSingleType();
if (singleType != null) {
LogicNode typeCheck = append(createInstanceOf(TypeReference.createExactTrusted(singleType), object, profile));
if (!typeCheck.isTautology()) {
append(new FixedGuardNode(typeCheck, DeoptimizationReason.TypeCheckedInliningViolated, DeoptimizationAction.InvalidateReprofile));
}
instanceOfNode = LogicConstantNode.forBoolean(resolvedType.getType().isAssignableFrom(singleType));
}
}
}
if (instanceOfNode == null) {
instanceOfNode = createInstanceOf(resolvedType, object, null);
}
LogicNode logicNode = genUnique(instanceOfNode);
int next = getStream().nextBCI();
int value = getStream().readUByte(next);
if (next <= currentBlock.endBci && (value == Bytecodes.IFEQ || value == Bytecodes.IFNE)) {
getStream().next();
BciBlock firstSucc = currentBlock.getSuccessor(0);
BciBlock secondSucc = currentBlock.getSuccessor(1);
if (firstSucc != secondSucc) {
boolean negate = value != Bytecodes.IFNE;
if (negate) {
BciBlock tmp = firstSucc;
firstSucc = secondSucc;
secondSucc = tmp;
}
genIf(instanceOfNode, firstSucc, secondSucc, getProfileProbability(negate));
} else {
appendGoto(firstSucc);
}
} else {
// Most frequent for value is IRETURN, followed by ISTORE.
frameState.push(JavaKind.Int, append(genConditional(logicNode)));
}
}
Aggregations