use of org.graalvm.compiler.phases.common.inlining.info.MultiTypeGuardInlineInfo in project graal by oracle.
the class InliningData method getTypeCheckedInlineInfo.
private InlineInfo getTypeCheckedInlineInfo(Invoke invoke, ResolvedJavaMethod targetMethod) {
JavaTypeProfile typeProfile = ((MethodCallTargetNode) invoke.callTarget()).getProfile();
if (typeProfile == null) {
InliningUtil.traceNotInlinedMethod(invoke, inliningDepth(), targetMethod, "no type profile exists");
return null;
}
JavaTypeProfile.ProfiledType[] ptypes = typeProfile.getTypes();
if (ptypes == null || ptypes.length <= 0) {
InliningUtil.traceNotInlinedMethod(invoke, inliningDepth(), targetMethod, "no types in profile");
return null;
}
ResolvedJavaType contextType = invoke.getContextType();
double notRecordedTypeProbability = typeProfile.getNotRecordedProbability();
final OptimisticOptimizations optimisticOpts = context.getOptimisticOptimizations();
OptionValues options = invoke.asNode().getOptions();
if (ptypes.length == 1 && notRecordedTypeProbability == 0) {
if (!optimisticOpts.inlineMonomorphicCalls(options)) {
InliningUtil.traceNotInlinedMethod(invoke, inliningDepth(), targetMethod, "inlining monomorphic calls is disabled");
return null;
}
ResolvedJavaType type = ptypes[0].getType();
assert type.isArray() || type.isConcrete();
ResolvedJavaMethod concrete = type.resolveConcreteMethod(targetMethod, contextType);
if (!checkTargetConditions(invoke, concrete)) {
return null;
}
return new TypeGuardInlineInfo(invoke, concrete, type);
} else {
invoke.setPolymorphic(true);
if (!optimisticOpts.inlinePolymorphicCalls(options) && notRecordedTypeProbability == 0) {
InliningUtil.traceNotInlinedMethod(invoke, inliningDepth(), targetMethod, "inlining polymorphic calls is disabled (%d types)", ptypes.length);
return null;
}
if (!optimisticOpts.inlineMegamorphicCalls(options) && notRecordedTypeProbability > 0) {
// due to filtering impossible types, notRecordedTypeProbability can be > 0 although
// the number of types is lower than what can be recorded in a type profile
InliningUtil.traceNotInlinedMethod(invoke, inliningDepth(), targetMethod, "inlining megamorphic calls is disabled (%d types, %f %% not recorded types)", ptypes.length, notRecordedTypeProbability * 100);
return null;
}
// Find unique methods and their probabilities.
ArrayList<ResolvedJavaMethod> concreteMethods = new ArrayList<>();
ArrayList<Double> concreteMethodsProbabilities = new ArrayList<>();
for (int i = 0; i < ptypes.length; i++) {
ResolvedJavaMethod concrete = ptypes[i].getType().resolveConcreteMethod(targetMethod, contextType);
if (concrete == null) {
InliningUtil.traceNotInlinedMethod(invoke, inliningDepth(), targetMethod, "could not resolve method");
return null;
}
int index = concreteMethods.indexOf(concrete);
double curProbability = ptypes[i].getProbability();
if (index < 0) {
index = concreteMethods.size();
concreteMethods.add(concrete);
concreteMethodsProbabilities.add(curProbability);
} else {
concreteMethodsProbabilities.set(index, concreteMethodsProbabilities.get(index) + curProbability);
}
}
// Clear methods that fall below the threshold.
if (notRecordedTypeProbability > 0) {
ArrayList<ResolvedJavaMethod> newConcreteMethods = new ArrayList<>();
ArrayList<Double> newConcreteMethodsProbabilities = new ArrayList<>();
for (int i = 0; i < concreteMethods.size(); ++i) {
if (concreteMethodsProbabilities.get(i) >= MegamorphicInliningMinMethodProbability.getValue(options)) {
newConcreteMethods.add(concreteMethods.get(i));
newConcreteMethodsProbabilities.add(concreteMethodsProbabilities.get(i));
}
}
if (newConcreteMethods.isEmpty()) {
// No method left that is worth inlining.
InliningUtil.traceNotInlinedMethod(invoke, inliningDepth(), targetMethod, "no methods remaining after filtering less frequent methods (%d methods previously)", concreteMethods.size());
return null;
}
concreteMethods = newConcreteMethods;
concreteMethodsProbabilities = newConcreteMethodsProbabilities;
}
if (concreteMethods.size() > maxMethodPerInlining) {
InliningUtil.traceNotInlinedMethod(invoke, inliningDepth(), targetMethod, "polymorphic call with more than %d target methods", maxMethodPerInlining);
return null;
}
// Clean out types whose methods are no longer available.
ArrayList<JavaTypeProfile.ProfiledType> usedTypes = new ArrayList<>();
ArrayList<Integer> typesToConcretes = new ArrayList<>();
for (JavaTypeProfile.ProfiledType type : ptypes) {
ResolvedJavaMethod concrete = type.getType().resolveConcreteMethod(targetMethod, contextType);
int index = concreteMethods.indexOf(concrete);
if (index == -1) {
notRecordedTypeProbability += type.getProbability();
} else {
assert type.getType().isArray() || !type.getType().isAbstract() : type + " " + concrete;
usedTypes.add(type);
typesToConcretes.add(index);
}
}
if (usedTypes.isEmpty()) {
// No type left that is worth checking for.
InliningUtil.traceNotInlinedMethod(invoke, inliningDepth(), targetMethod, "no types remaining after filtering less frequent types (%d types previously)", ptypes.length);
return null;
}
for (ResolvedJavaMethod concrete : concreteMethods) {
if (!checkTargetConditions(invoke, concrete)) {
InliningUtil.traceNotInlinedMethod(invoke, inliningDepth(), targetMethod, "it is a polymorphic method call and at least one invoked method cannot be inlined");
return null;
}
}
return new MultiTypeGuardInlineInfo(invoke, concreteMethods, usedTypes, typesToConcretes, notRecordedTypeProbability);
}
}
Aggregations