Search in sources :

Example 1 with SpecializationData

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);
}
Also used : CodeExecutableElement(com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement) SpecializationData(com.oracle.truffle.dsl.processor.model.SpecializationData) ArrayList(java.util.ArrayList) DeclaredCodeTypeMirror(com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.DeclaredCodeTypeMirror) Introspection(com.oracle.truffle.api.dsl.Introspection) CacheExpression(com.oracle.truffle.dsl.processor.model.CacheExpression) DeclaredCodeTypeMirror(com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.DeclaredCodeTypeMirror) ArrayCodeTypeMirror(com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror) GeneratedTypeMirror(com.oracle.truffle.dsl.processor.java.model.GeneratedTypeMirror) TypeMirror(javax.lang.model.type.TypeMirror) ElementUtils.isObject(com.oracle.truffle.dsl.processor.java.ElementUtils.isObject) Arrays(java.util.Arrays) CodeTreeBuilder(com.oracle.truffle.dsl.processor.java.model.CodeTreeBuilder) ArrayCodeTypeMirror(com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror)

Example 2 with SpecializationData

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();
}
Also used : CodeTree(com.oracle.truffle.dsl.processor.java.model.CodeTree) ArrayList(java.util.ArrayList) SpecializationData(com.oracle.truffle.dsl.processor.model.SpecializationData) CodeTreeBuilder(com.oracle.truffle.dsl.processor.java.model.CodeTreeBuilder)

Example 3 with SpecializationData

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);
}
Also used : CodeTree(com.oracle.truffle.dsl.processor.java.model.CodeTree) SpecializationData(com.oracle.truffle.dsl.processor.model.SpecializationData) Parameter(com.oracle.truffle.dsl.processor.model.Parameter)

Example 4 with SpecializationData

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;
}
Also used : CodeExecutableElement(com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement) SpecializationData(com.oracle.truffle.dsl.processor.model.SpecializationData) SpecializationGroup(com.oracle.truffle.dsl.processor.parser.SpecializationGroup) CodeTreeBuilder(com.oracle.truffle.dsl.processor.java.model.CodeTreeBuilder)

Example 5 with SpecializationData

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();
}
Also used : GuardExpression(com.oracle.truffle.dsl.processor.model.GuardExpression) ArrayList(java.util.ArrayList) SpecializationData(com.oracle.truffle.dsl.processor.model.SpecializationData) SpecializationGroup(com.oracle.truffle.dsl.processor.parser.SpecializationGroup) DSLExpression(com.oracle.truffle.dsl.processor.expression.DSLExpression) CodeTree(com.oracle.truffle.dsl.processor.java.model.CodeTree) List(java.util.List) ArrayList(java.util.ArrayList) CodeTreeBuilder(com.oracle.truffle.dsl.processor.java.model.CodeTreeBuilder) TypeGuard(com.oracle.truffle.dsl.processor.parser.SpecializationGroup.TypeGuard) AssumptionExpression(com.oracle.truffle.dsl.processor.model.AssumptionExpression)

Aggregations

SpecializationData (com.oracle.truffle.dsl.processor.model.SpecializationData)35 ArrayList (java.util.ArrayList)22 TypeMirror (javax.lang.model.type.TypeMirror)17 ArrayCodeTypeMirror (com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror)16 CodeTreeBuilder (com.oracle.truffle.dsl.processor.java.model.CodeTreeBuilder)12 CodeExecutableElement (com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement)11 DeclaredCodeTypeMirror (com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.DeclaredCodeTypeMirror)11 GeneratedTypeMirror (com.oracle.truffle.dsl.processor.java.model.GeneratedTypeMirror)11 Parameter (com.oracle.truffle.dsl.processor.model.Parameter)9 CodeVariableElement (com.oracle.truffle.dsl.processor.java.model.CodeVariableElement)8 ExecutableTypeData (com.oracle.truffle.dsl.processor.model.ExecutableTypeData)7 CodeTree (com.oracle.truffle.dsl.processor.java.model.CodeTree)6 HashSet (java.util.HashSet)6 NodeExecutionData (com.oracle.truffle.dsl.processor.model.NodeExecutionData)5 VariableElement (javax.lang.model.element.VariableElement)5 AnnotationValue (javax.lang.model.element.AnnotationValue)4 ExecutableElement (javax.lang.model.element.ExecutableElement)4 Child (com.oracle.truffle.api.nodes.Node.Child)3 DSLExpression (com.oracle.truffle.dsl.processor.expression.DSLExpression)3 ElementUtils.isObject (com.oracle.truffle.dsl.processor.java.ElementUtils.isObject)3