use of com.oracle.truffle.dsl.processor.parser.SpecializationGroup.TypeGuard in project graal by oracle.
the class FlatNodeGenFactory method visitSpecializationGroup.
private CodeTree visitSpecializationGroup(CodeTreeBuilder parent, SpecializationGroup group, ExecutableTypeData forType, FrameState frameState, List<SpecializationData> allowedSpecializations, NodeExecutionMode mode) {
CodeTreeBuilder builder = parent.create();
boolean hasFallthrough = false;
boolean hasImplicitCast = false;
List<IfTriple> cachedTriples = new ArrayList<>();
for (TypeGuard guard : group.getTypeGuards()) {
IfTriple triple = createTypeCheckOrCast(frameState, group, guard, mode, false, true);
if (triple != null) {
cachedTriples.add(triple);
}
hasImplicitCast = hasImplicitCast || node.getTypeSystem().hasImplicitSourceTypes(guard.getType());
if (!mode.isGuardFallback()) {
triple = createTypeCheckOrCast(frameState, group, guard, mode, true, true);
if (triple != null) {
cachedTriples.add(triple);
}
}
}
SpecializationData specialization = group.getSpecialization();
SpecializationData[] specializations = group.collectSpecializations().toArray(new SpecializationData[0]);
List<GuardExpression> guardExpressions = new ArrayList<>(group.getGuards());
// out of the loop.
if (specialization != null && specialization.hasMultipleInstances()) {
List<GuardExpression> unboundGuards = new ArrayList<>();
for (GuardExpression guard : guardExpressions) {
if (!specialization.isGuardBoundWithCache(guard)) {
unboundGuards.add(guard);
} else {
// we need to stop as we need to ensure guard execution order
break;
}
}
cachedTriples.addAll(createMethodGuardCheck(frameState, group, unboundGuards, mode));
guardExpressions.removeAll(unboundGuards);
}
boolean useSpecializationClass = specialization != null && useSpecializationClass(specialization);
if (mode.isFastPath()) {
int ifCount = 0;
final boolean stateGuaranteed = group.isLast() && allowedSpecializations != null && allowedSpecializations.size() == 1 && group.getAllSpecializations().size() == allowedSpecializations.size();
if ((!group.isEmpty() || specialization != null)) {
CodeTree stateCheck = state.createContains(frameState, specializations);
CodeTree stateGuard = null;
CodeTree assertCheck = null;
if (stateGuaranteed) {
assertCheck = CodeTreeBuilder.createBuilder().startAssert().tree(stateCheck).end().build();
} else {
stateGuard = stateCheck;
}
cachedTriples.add(0, new IfTriple(null, stateGuard, assertCheck));
}
ifCount += IfTriple.materialize(builder, IfTriple.optimize(cachedTriples), false);
// reset current triples
cachedTriples = new ArrayList<>();
String specializationLocalName = null;
if (useSpecializationClass) {
specializationLocalName = createSpecializationLocalName(specialization);
builder.tree(loadSpecializationClass(frameState, specialization));
if (specialization.getMaximumNumberOfInstances() > 1) {
builder.startWhile();
} else {
builder.startIf();
}
builder.string(specializationLocalName, " != null");
builder.end();
builder.startBlock();
ifCount++;
}
if (specialization != null) {
if (!specialization.getAssumptionExpressions().isEmpty()) {
builder.tree(createFastPathAssumptionCheck(builder, specialization, forType, frameState));
}
}
cachedTriples = createMethodGuardCheck(frameState, group, guardExpressions, mode);
int innerIfCount = IfTriple.materialize(builder, IfTriple.optimize(cachedTriples), false);
SpecializationGroup prev = null;
for (SpecializationGroup child : group.getChildren()) {
if (prev != null && !prev.hasFallthrough()) {
break;
}
builder.tree(visitSpecializationGroup(builder, child, forType, frameState.copy(), allowedSpecializations, mode));
}
if (specialization != null && (prev == null || prev.hasFallthrough())) {
builder.tree(createFastPathExecute(builder, forType, specialization, frameState));
}
builder.end(innerIfCount);
hasFallthrough |= innerIfCount > 0;
if (useSpecializationClass && specialization.getMaximumNumberOfInstances() > 1) {
String name = createSpecializationLocalName(specialization);
builder.startStatement().string(name, " = ", name, ".next_").end();
}
builder.end(ifCount);
hasFallthrough |= ifCount > 0;
} else if (mode.isSlowPath()) {
if (specialization != null && mayBeExcluded(specialization)) {
CodeTree excludeCheck = exclude.createNotContains(frameState, specializations);
cachedTriples.add(0, new IfTriple(null, excludeCheck, null));
}
int outerIfCount = 0;
if (specialization == null) {
cachedTriples.addAll(createMethodGuardCheck(frameState, group, guardExpressions, mode));
outerIfCount += IfTriple.materialize(builder, IfTriple.optimize(cachedTriples), false);
SpecializationGroup prev = null;
for (SpecializationGroup child : group.getChildren()) {
if (prev != null && !prev.hasFallthrough()) {
break;
}
builder.tree(visitSpecializationGroup(builder, child, forType, frameState.copy(), allowedSpecializations, mode));
prev = child;
}
} else {
outerIfCount += IfTriple.materialize(builder, IfTriple.optimize(cachedTriples), false);
String countName = specialization != null ? "count" + specialization.getIndex() + "_" : null;
boolean needsDuplicationCheck = specialization.isGuardBindsCache() || specialization.hasMultipleInstances();
boolean useDuplicateFlag = specialization.isGuardBindsCache() && !specialization.hasMultipleInstances();
String duplicateFoundName = specialization.getId() + "_duplicateFound_";
int innerIfCount = 0;
String specializationLocalName = createSpecializationLocalName(specialization);
if (needsDuplicationCheck) {
builder.tree(createDuplicationCheck(builder, frameState, group, guardExpressions, useDuplicateFlag, countName, duplicateFoundName, specializationLocalName));
builder.startIf();
if (useDuplicateFlag) {
// we reuse the specialization class local name instead of a duplicate found
// name
builder.string("!", duplicateFoundName);
} else {
builder.string(createSpecializationLocalName(specialization), " == null");
}
builder.end().startBlock();
innerIfCount++;
}
List<IfTriple> innerTripples = createMethodGuardCheck(frameState, group, guardExpressions, mode);
List<AssumptionExpression> assumptions = specialization.getAssumptionExpressions();
if (!assumptions.isEmpty()) {
for (AssumptionExpression assumption : assumptions) {
innerTripples.addAll(createAssumptionSlowPathTriples(frameState, group, assumption));
}
}
if (specialization.hasMultipleInstances()) {
DSLExpression limit = specialization.getLimitExpression();
innerTripples.addAll(initializeCaches(frameState, group, specialization.getBoundCaches(limit), NodeExecutionMode.SLOW_PATH, true, false));
CodeTree limitExpression = DSLExpressionGenerator.write(limit, null, castBoundTypes(bindExpressionValues(frameState, limit, specialization)));
CodeTree limitCondition = CodeTreeBuilder.createBuilder().string(countName).string(" < ").tree(limitExpression).build();
innerTripples.add(new IfTriple(null, limitCondition, null));
// assert that specialization is not initialized
// otherwise we have been inserting invalid instances
assertSpecializationClassNotInitialized(frameState, specialization);
} else if (needsDuplicationCheck) {
innerTripples.add(new IfTriple(null, state.createNotContains(frameState, new Object[] { specialization }), null));
}
innerIfCount += IfTriple.materialize(builder, IfTriple.optimize(innerTripples), false);
builder.tree(createSpecialize(builder, frameState, group, specialization));
if (needsDuplicationCheck) {
hasFallthrough = true;
if (useDuplicateFlag) {
builder.startStatement().string(duplicateFoundName, " = true").end();
}
builder.end(innerIfCount);
// need to ensure that we update the implicit cast specializations on duplicates
CodeTree updateImplicitCast = createUpdateImplicitCastState(builder, frameState, specialization);
if (updateImplicitCast != null) {
builder.startElseBlock();
builder.tree(createUpdateImplicitCastState(builder, frameState, specialization));
builder.tree(state.createSet(frameState, new Object[] { specialization }, true, true));
builder.end();
}
builder.startIf();
if (useDuplicateFlag) {
builder.string(duplicateFoundName);
} else {
builder.string(createSpecializationLocalName(specialization), " != null");
}
builder.end().startBlock();
builder.tree(createExecute(builder, frameState, executeAndSpecializeType, specialization, mode));
builder.end();
} else {
builder.tree(createExecute(builder, frameState, executeAndSpecializeType, specialization, mode));
builder.end(innerIfCount);
hasFallthrough |= innerIfCount > 0;
}
}
builder.end(outerIfCount);
hasFallthrough |= outerIfCount > 0;
} else if (mode.isGuardFallback()) {
int ifCount = 0;
if (specialization != null && specialization.getMaximumNumberOfInstances() > 1) {
throw new AssertionError("unsupported path. should be caught by parser..");
}
int innerIfCount = 0;
cachedTriples.addAll(createMethodGuardCheck(frameState, group, guardExpressions, mode));
cachedTriples.addAll(createAssumptionCheckTriples(frameState, specialization));
cachedTriples = IfTriple.optimize(cachedTriples);
if (specialization != null && !hasImplicitCast) {
IfTriple singleCondition = null;
if (cachedTriples.size() == 1) {
singleCondition = cachedTriples.get(0);
}
if (singleCondition != null) {
int index = cachedTriples.indexOf(singleCondition);
CodeTree stateCheck = state.createNotContains(frameState, specializations);
cachedTriples.set(index, new IfTriple(singleCondition.prepare, combineTrees(" && ", stateCheck, singleCondition.condition), singleCondition.statements));
fallbackNeedsState = true;
}
}
innerIfCount += IfTriple.materialize(builder, cachedTriples, false);
SpecializationGroup prev = null;
for (SpecializationGroup child : group.getChildren()) {
if (prev != null && !prev.hasFallthrough()) {
break;
}
builder.tree(visitSpecializationGroup(builder, child, forType, frameState.copy(), allowedSpecializations, mode));
prev = child;
}
if (specialization != null) {
builder.returnFalse();
}
builder.end(innerIfCount);
builder.end(ifCount);
hasFallthrough |= ifCount > 0 || innerIfCount > 0;
} else {
throw new AssertionError("unexpected path");
}
group.setFallthrough(hasFallthrough);
return builder.build();
}
use of com.oracle.truffle.dsl.processor.parser.SpecializationGroup.TypeGuard in project graal by oracle.
the class FlatNodeGenFactory method createUpdateImplicitCastState.
private CodeTree createUpdateImplicitCastState(CodeTreeBuilder parent, FrameState frameState, SpecializationData specialization) {
CodeTreeBuilder builder = null;
int signatureIndex = 0;
for (Parameter p : specialization.getSignatureParameters()) {
TypeMirror targetType = p.getType();
TypeMirror polymorphicType = node.getPolymorphicSpecialization().findParameterOrDie(p.getSpecification().getExecution()).getType();
if (typeSystem.hasImplicitSourceTypes(targetType) && needsCastTo(polymorphicType, targetType)) {
String implicitFieldName = createImplicitTypeStateLocalName(p);
if (builder == null) {
builder = parent.create();
}
builder.tree(state.createSetInteger(frameState, new TypeGuard(p.getType(), signatureIndex), CodeTreeBuilder.singleString(implicitFieldName)));
}
signatureIndex++;
}
return builder == null ? null : builder.build();
}
use of com.oracle.truffle.dsl.processor.parser.SpecializationGroup.TypeGuard in project graal by oracle.
the class FlatNodeGenFactory method createExecuteChildImplicitCast.
private ChildExecutionResult createExecuteChildImplicitCast(CodeTreeBuilder parent, FrameState originalFrameState, FrameState frameState, NodeExecutionData execution, LocalVariable target) {
CodeTreeBuilder builder = parent.create();
List<TypeMirror> originalSourceTypes = typeSystem.lookupSourceTypes(target.getTypeMirror());
List<TypeMirror> sourceTypes = resolveOptimizedImplicitSourceTypes(execution, target.getTypeMirror());
TypeGuard typeGuard = new TypeGuard(target.getTypeMirror(), execution.getIndex());
boolean throwsUnexpected = false;
boolean elseIf = false;
for (TypeMirror sourceType : sourceTypes) {
ExecutableTypeData executableType = resolveTargetExecutable(execution, sourceType);
elseIf = builder.startIf(elseIf);
throwsUnexpected |= executableType.hasUnexpectedValue(context);
builder.startGroup();
builder.tree(state.createContainsOnly(frameState, originalSourceTypes.indexOf(sourceType), 1, new Object[] { typeGuard }, new Object[] { typeGuard }));
builder.string(" && ");
builder.tree(state.createIsNotAny(frameState, reachableSpecializationsArray));
builder.end();
builder.end();
builder.startBlock();
CodeTree value = callChildExecuteMethod(execution, executableType, frameState);
value = expect(executableType.getReturnType(), sourceType, value);
throwsUnexpected |= needsCastTo(executableType.getReturnType(), sourceType);
ImplicitCastData cast = typeSystem.lookupCast(sourceType, target.getTypeMirror());
if (cast != null) {
// we need to store the original value to restore it in
// case of a deopt
String localName = createSourceTypeLocalName(target, sourceType);
builder.startStatement().string(localName).string(" = ").tree(value).end();
value = callMethod(null, cast.getMethod(), CodeTreeBuilder.singleString(localName));
}
builder.startStatement().string(target.getName()).string(" = ").tree(value).end();
builder.end();
}
if (elseIf) {
builder.startElseBlock();
}
LocalVariable genericValue = target.makeGeneric(context).nextName();
builder.tree(createAssignExecuteChild(originalFrameState, frameState, builder, execution, node.getGenericExecutableType(null), genericValue));
builder.startStatement().string(target.getName()).string(" = ");
CodeTree implicitState = state.createExtractInteger(frameState, typeGuard);
builder.tree(TypeSystemCodeGenerator.implicitExpectFlat(typeSystem, target.getTypeMirror(), genericValue.createReference(), implicitState));
builder.end();
if (!sourceTypes.isEmpty()) {
builder.end();
}
return new ChildExecutionResult(builder.build(), throwsUnexpected);
}
use of com.oracle.truffle.dsl.processor.parser.SpecializationGroup.TypeGuard in project graal by oracle.
the class FlatNodeGenFactory method createFastPath.
private CodeTree createFastPath(CodeTreeBuilder parent, List<SpecializationData> allSpecializations, SpecializationGroup originalGroup, final ExecutableTypeData currentType, FrameState frameState) {
final CodeTreeBuilder builder = parent.create();
builder.tree(state.createLoad(frameState));
int sharedExecutes = 0;
for (NodeExecutionData execution : node.getChildExecutions()) {
boolean canExecuteChild = execution.getIndex() < currentType.getEvaluatedCount();
for (TypeGuard checkedGuard : originalGroup.getTypeGuards()) {
if (checkedGuard.getSignatureIndex() == execution.getIndex()) {
canExecuteChild = true;
break;
}
}
if (!canExecuteChild) {
break;
}
for (TypeGuard checkedGuard : originalGroup.getTypeGuards()) {
// we cannot pull out guards that use optimized implicit source types
if (resolveOptimizedImplicitSourceTypes(execution, checkedGuard.getType()).size() > 1) {
canExecuteChild = false;
break;
}
}
if (!canExecuteChild) {
break;
}
builder.tree(createFastPathExecuteChild(builder, frameState.copy(), frameState, currentType, originalGroup, execution));
sharedExecutes++;
}
List<BoxingSplit> boxingSplits = parameterBoxingElimination(originalGroup, sharedExecutes);
if (boxingSplits.isEmpty()) {
builder.tree(executeFastPathGroup(builder, frameState, currentType, originalGroup, sharedExecutes, null));
addExplodeLoop(builder, originalGroup);
} else {
FrameState originalFrameState = frameState.copy();
boolean elseIf = false;
for (BoxingSplit split : boxingSplits) {
elseIf = builder.startIf(elseIf);
List<SpecializationData> specializations = split.group.collectSpecializations();
builder.startGroup();
builder.tree(state.createContainsOnly(frameState, 0, -1, specializations.toArray(), allSpecializations.toArray())).end();
builder.string(" && ");
builder.tree(state.createIsNotAny(frameState, allSpecializations.toArray()));
builder.end();
builder.end().startBlock();
builder.tree(wrapInAMethod(builder, split.group, originalFrameState, split.getName(), executeFastPathGroup(builder, frameState.copy(), currentType, split.group, sharedExecutes, specializations)));
builder.end();
}
builder.startElseBlock();
builder.tree(wrapInAMethod(builder, originalGroup, originalFrameState, "generic", executeFastPathGroup(builder, frameState, currentType, originalGroup, sharedExecutes, null)));
builder.end();
}
return builder.build();
}
use of com.oracle.truffle.dsl.processor.parser.SpecializationGroup.TypeGuard in project graal by oracle.
the class FlatNodeGenFactory method parameterBoxingElimination.
/*
* It duplicates a group into small subgroups of specializations that don't need boxing when
* executing the children.
*/
private List<BoxingSplit> parameterBoxingElimination(SpecializationGroup group, int evaluatedcount) {
if (!boxingEliminationEnabled) {
return Collections.emptyList();
}
List<SpecializationData> allSpecializations = group.collectSpecializations();
List<Set<TypeGuard>> signatures = new ArrayList<>();
List<List<SpecializationData>> signatureSpecializations = new ArrayList<>();
for (SpecializationData specialization : allSpecializations) {
int index = -1;
List<TypeGuard> guards = new ArrayList<>();
for (Parameter p : specialization.getSignatureParameters()) {
index++;
if (!ElementUtils.isPrimitive(p.getType())) {
continue;
} else if (index < evaluatedcount) {
continue;
} else {
NodeChildData child = p.getSpecification().getExecution().getChild();
if (child != null && child.findExecutableType(p.getType()) == null) {
// type cannot be executed so it cannot be eliminated
continue;
}
}
guards.add(new TypeGuard(p.getType(), index));
}
if (!guards.isEmpty()) {
boolean directFound = false;
for (int i = 0; i < signatures.size(); i++) {
if (guards.containsAll(signatures.get(i))) {
if (signatures.get(i).containsAll(guards)) {
directFound = true;
}
signatureSpecializations.get(i).add(specialization);
}
}
if (!directFound) {
signatures.add(new LinkedHashSet<>(guards));
List<SpecializationData> specializations = new ArrayList<>();
specializations.add(specialization);
signatureSpecializations.add(specializations);
}
}
}
List<BoxingSplit> groups = new ArrayList<>();
for (int i = 0; i < signatureSpecializations.size(); i++) {
List<SpecializationData> groupedSpecialization = signatureSpecializations.get(i);
if (allSpecializations.size() == groupedSpecialization.size()) {
// contains all specializations does not make sense to group
continue;
}
Set<TypeGuard> signature = signatures.get(i);
TypeMirror[] signatureMirrors = new TypeMirror[signature.size()];
int index = 0;
for (TypeGuard typeGuard : signature) {
signatureMirrors[index] = typeGuard.getType();
index++;
}
groups.add(new BoxingSplit(SpecializationGroup.create(groupedSpecialization), signatureMirrors));
}
Collections.sort(groups, new Comparator<BoxingSplit>() {
public int compare(BoxingSplit o1, BoxingSplit o2) {
return Integer.compare(o2.primitiveSignature.length, o1.primitiveSignature.length);
}
});
return groups;
}
Aggregations