use of com.oracle.truffle.dsl.processor.model.SpecializationData in project graal by oracle.
the class FlatNodeGenFactory method generateReflectionInfo.
private void generateReflectionInfo(CodeTypeElement clazz) {
clazz.getImplements().add(context.getType(Introspection.Provider.class));
CodeExecutableElement reflection = new CodeExecutableElement(modifiers(PUBLIC), context.getType(Introspection.class), "getIntrospectionData");
CodeTreeBuilder builder = reflection.createBuilder();
List<SpecializationData> filteredSpecializations = new ArrayList<>();
for (SpecializationData s : node.getSpecializations()) {
if (s.getMethod() == null) {
continue;
}
filteredSpecializations.add(s);
}
ArrayCodeTypeMirror objectArray = new ArrayCodeTypeMirror(context.getType(Object.class));
builder.declaration(objectArray, "data", builder.create().startNewArray(objectArray, CodeTreeBuilder.singleString(String.valueOf(filteredSpecializations.size() + 1))).end().build());
builder.declaration(objectArray, "s", (CodeTree) null);
// declare version 0
builder.statement("data[0] = 0");
FrameState frameState = FrameState.load(this);
builder.tree(state.createLoad(frameState));
if (requiresExclude()) {
builder.tree(exclude.createLoad(frameState));
}
int index = 1;
for (SpecializationData specialization : filteredSpecializations) {
builder.startStatement().string("s = ").startNewArray(objectArray, CodeTreeBuilder.singleString("3")).end().end();
builder.startStatement().string("s[0] = ").doubleQuote(specialization.getMethodName()).end();
builder.startIf().tree(state.createContains(frameState, new Object[] { specialization })).end().startBlock();
builder.startStatement().string("s[1] = (byte)0b01 /* active */").end();
TypeMirror listType = new DeclaredCodeTypeMirror((TypeElement) context.getDeclaredType(ArrayList.class).asElement(), Arrays.asList(context.getType(Object.class)));
if (!specialization.getCaches().isEmpty()) {
builder.declaration(listType, "cached", "new ArrayList<>()");
boolean useSpecializationClass = useSpecializationClass(specialization);
String name = createSpecializationLocalName(specialization);
if (useSpecializationClass) {
builder.tree(loadSpecializationClass(frameState, specialization));
if (specialization.hasMultipleInstances()) {
builder.startWhile();
} else {
builder.startIf();
}
builder.string(name, " != null");
builder.end();
builder.startBlock();
}
builder.startStatement().startCall("cached", "add");
builder.startStaticCall(context.getType(Arrays.class), "asList");
for (CacheExpression cache : specialization.getCaches()) {
builder.startGroup();
builder.tree(createCacheReference(frameState, specialization, cache.getParameter()));
builder.end();
}
builder.end();
builder.end().end();
if (useSpecializationClass) {
if (specialization.getMaximumNumberOfInstances() > 1) {
builder.startStatement().string(name, " = ", name, ".next_").end();
}
// cache while or if
builder.end();
}
builder.statement("s[2] = cached");
}
builder.end();
if (mayBeExcluded(specialization)) {
builder.startElseIf().tree(exclude.createContains(frameState, new Object[] { specialization })).end().startBlock();
builder.startStatement().string("s[1] = (byte)0b10 /* excluded */").end();
builder.end();
}
builder.startElseBlock();
builder.startStatement().string("s[1] = (byte)0b00 /* inactive */").end();
builder.end();
builder.startStatement().string("data[", String.valueOf(index), "] = s").end();
index++;
}
builder.startReturn().startStaticCall(context.getType(Introspection.Provider.class), "create").string("data").end().end();
clazz.add(reflection);
}
use of com.oracle.truffle.dsl.processor.model.SpecializationData in project graal by oracle.
the class FlatNodeGenFactory method createSpecialize.
private CodeTree createSpecialize(CodeTreeBuilder parent, FrameState frameState, SpecializationGroup group, SpecializationData specialization) {
CodeTreeBuilder builder = parent.create();
List<IfTriple> triples = new ArrayList<>();
triples.addAll(initializeSpecializationClass(frameState, specialization));
triples.addAll(initializeCaches(frameState, group, specialization.getCaches(), NodeExecutionMode.SLOW_PATH, false, true));
triples.addAll(persistAssumptions(frameState, specialization));
triples.addAll(persistSpecializationClass(frameState, specialization));
builder.end(IfTriple.materialize(builder, triples, true));
List<SpecializationData> excludesSpecializations = new ArrayList<>();
for (SpecializationData otherSpeciailzation : reachableSpecializations) {
if (otherSpeciailzation == specialization) {
continue;
}
if (otherSpeciailzation.getExcludedBy().contains(specialization)) {
excludesSpecializations.add(otherSpeciailzation);
}
}
if (!excludesSpecializations.isEmpty()) {
SpecializationData[] excludesArray = excludesSpecializations.toArray(new SpecializationData[0]);
builder.tree(exclude.createSet(frameState, excludesArray, true, true));
for (SpecializationData excludes : excludesArray) {
if (useSpecializationClass(excludes)) {
builder.statement("this." + createSpecializationFieldName(excludes) + " = null");
}
}
builder.tree((state.createSet(frameState, excludesArray, false, false)));
}
CodeTree updateImplicitCast = createUpdateImplicitCastState(builder, frameState, specialization);
if (updateImplicitCast != null) {
builder.tree(createUpdateImplicitCastState(builder, frameState, specialization));
}
builder.tree(state.createSet(frameState, new SpecializationData[] { specialization }, true, true));
return builder.build();
}
use of com.oracle.truffle.dsl.processor.model.SpecializationData in project graal by oracle.
the class FlatNodeGenFactory method callTemplateMethod.
private CodeTree callTemplateMethod(CodeTree receiver, TemplateMethod method, FrameState frameState) {
CodeTree[] bindings = new CodeTree[method.getParameters().size()];
int signatureIndex = 0;
for (int i = 0; i < bindings.length; i++) {
Parameter parameter = method.getParameters().get(i);
if (parameter.getSpecification().isCached() && method instanceof SpecializationData) {
bindings[i] = createCacheReference(frameState, (SpecializationData) method, parameter);
} else {
LocalVariable var = frameState.get(parameter, signatureIndex);
if (var == null) {
var = frameState.get(parameter.getLocalName());
}
if (var != null) {
bindings[i] = createParameterReference(var, method.getMethod(), i);
}
}
if (parameter.getSpecification().isSignature()) {
signatureIndex++;
}
}
return callMethod(receiver, method.getMethod(), bindings);
}
use of com.oracle.truffle.dsl.processor.model.SpecializationData in project graal by oracle.
the class FlatNodeGenFactory method createExecute.
private CodeExecutableElement createExecute(CodeTypeElement clazz, ExecutableTypeData type, List<ExecutableTypeData> delegateableTypes) {
final List<SpecializationData> allSpecializations = reachableSpecializations;
final List<SpecializationData> compatibleSpecializations = filterCompatibleSpecializations(type, allSpecializations);
List<SpecializationData> implementedSpecializations;
if (delegateableTypes.isEmpty()) {
implementedSpecializations = compatibleSpecializations;
} else {
implementedSpecializations = filterImplementedSpecializations(type, compatibleSpecializations);
}
FrameState frameState = FrameState.load(this, type, Integer.MAX_VALUE);
CodeExecutableElement method = createExecuteMethod(null, type, frameState, true);
clazz.add(method);
CodeTreeBuilder builder = method.createBuilder();
// do I miss specializations that are reachable from this executable?
if (compatibleSpecializations.size() != implementedSpecializations.size()) {
ExecuteDelegationResult delegation = createExecuteDelegation(builder, frameState, type, delegateableTypes, compatibleSpecializations, implementedSpecializations);
builder.tree(delegation.tree);
if (!delegation.hasFallthrough) {
return method;
}
}
if (implementedSpecializations.isEmpty()) {
implementedSpecializations = compatibleSpecializations;
}
if (implementedSpecializations.isEmpty()) {
builder.tree(createTransferToInterpreterAndInvalidate());
builder.startThrow().startNew(getType(AssertionError.class)).doubleQuote("Delegation failed.").end().end();
} else {
SpecializationGroup group = SpecializationGroup.create(implementedSpecializations);
builder.tree(createFastPath(builder, implementedSpecializations, group, type, frameState));
}
return method;
}
use of com.oracle.truffle.dsl.processor.model.SpecializationData 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();
}
Aggregations