Search in sources :

Example 1 with LibraryData

use of com.oracle.truffle.dsl.processor.library.LibraryData in project graal by oracle.

the class NodeParser method parseCachedLibraries.

private SpecializationData parseCachedLibraries(SpecializationData specialization, DSLExpressionResolver resolver, List<CacheExpression> libraries) {
    SpecializationData uncachedSpecialization = null;
    List<CacheExpression> uncachedLibraries = null;
    /*
         * No uncached specialization needed if there is a specialization that is strictly more
         * generic than this one.
         */
    if (!specialization.isReplaced()) {
        uncachedSpecialization = specialization.copy();
        uncachedLibraries = new ArrayList<>();
        uncachedSpecialization.getReplaces().add(specialization);
        List<CacheExpression> caches = uncachedSpecialization.getCaches();
        for (int i = 0; i < caches.size(); i++) {
            CacheExpression expression = caches.get(i);
            if (expression.getCachedLibraryExpression() != null) {
                expression = expression.copy();
                caches.set(i, expression);
                uncachedLibraries.add(expression);
            }
        }
        specialization.setUncachedSpecialization(uncachedSpecialization);
    }
    if (uncachedLibraries != null && uncachedLibraries.size() != libraries.size()) {
        throw new AssertionError("Unexpected number of uncached libraries.");
    }
    boolean seenDynamicParameterBound = false;
    for (int i = 0; i < libraries.size(); i++) {
        CacheExpression cachedLibrary = libraries.get(i);
        CacheExpression uncachedLibrary = uncachedLibraries != null ? uncachedLibraries.get(i) : null;
        TypeMirror parameterType = cachedLibrary.getParameter().getType();
        TypeElement type = ElementUtils.fromTypeMirror(parameterType);
        if (type == null) {
            cachedLibrary.addError("Invalid library type %s. Must be a declared type.", getSimpleName(parameterType));
            continue;
        }
        if (!ElementUtils.isAssignable(parameterType, types.Library)) {
            cachedLibrary.addError("Invalid library type %s. Library is not a subclass of %s.", getSimpleName(parameterType), types.Library.asElement().getSimpleName().toString());
            continue;
        }
        if (ElementUtils.findAnnotationMirror(cachedLibrary.getParameter().getVariableElement(), types.Cached_Shared) != null) {
            cachedLibrary.addError("Specialized cached libraries cannot be shared yet.");
            continue;
        }
        Map<TypeElement, LibraryData> libraryCache = ProcessorContext.getInstance().getCacheMap(LibraryParser.class);
        LibraryData parsedLibrary = libraryCache.computeIfAbsent(type, (t) -> new LibraryParser().parse(t));
        if (parsedLibrary == null || parsedLibrary.hasErrors()) {
            cachedLibrary.addError("Library '%s' has errors. Please resolve them first.", getSimpleName(parameterType));
            continue;
        }
        cachedLibrary.setCachedLibrary(parsedLibrary);
        if (uncachedLibrary != null) {
            uncachedLibrary.setCachedLibrary(parsedLibrary);
        }
        String expression = cachedLibrary.getCachedLibraryExpression();
        DSLExpression receiverExpression = parseCachedExpression(resolver, cachedLibrary, parsedLibrary.getSignatureReceiverType(), expression);
        if (receiverExpression == null) {
            continue;
        }
        DSLExpression substituteCachedExpression = null;
        DSLExpression substituteUncachedExpression = null;
        // try substitutions
        if (mode == ParseMode.EXPORTED_MESSAGE) {
            Parameter receiverParameter = specialization.findParameterOrDie(specialization.getNode().getChildExecutions().get(0));
            if (receiverExpression instanceof DSLExpression.Variable) {
                DSLExpression.Variable variable = (DSLExpression.Variable) receiverExpression;
                if (variable.getReceiver() == null) {
                    VariableElement resolvedVariable = variable.getResolvedVariable();
                    if (ElementUtils.variableEquals(resolvedVariable, receiverParameter.getVariableElement())) {
                        // receiver
                        if (typeEquals(type.asType(), exportLibraryType)) {
                            DSLExpression.Variable nodeReceiver = new DSLExpression.Variable(null, "this");
                            nodeReceiver.setResolvedTargetType(exportLibraryType);
                            nodeReceiver.setResolvedVariable(new CodeVariableElement(exportLibraryType, "this"));
                            if (substituteThisToParent) {
                                DSLExpression.Call call = new DSLExpression.Call(nodeReceiver, "getParent", Collections.emptyList());
                                call.setResolvedMethod(ElementUtils.findMethod(types.Node, "getParent"));
                                call.setResolvedTargetType(context.getType(Object.class));
                                substituteCachedExpression = new DSLExpression.Cast(call, exportLibraryType);
                            } else {
                                substituteCachedExpression = nodeReceiver;
                            }
                        }
                    }
                }
            }
            if (substituteCachedExpression == null && supportsLibraryMerge(receiverExpression, receiverParameter.getVariableElement())) {
                substituteCachedExpression = receiverExpression;
                cachedLibrary.setMergedLibrary(true);
            }
        }
        if (substituteCachedExpression != null) {
            if (substituteUncachedExpression == null) {
                substituteUncachedExpression = substituteCachedExpression;
            }
            cachedLibrary.setDefaultExpression(substituteCachedExpression);
            cachedLibrary.setUncachedExpression(substituteUncachedExpression);
            cachedLibrary.setAlwaysInitialized(true);
            continue;
        } else {
            seenDynamicParameterBound |= specialization.isDynamicParameterBound(receiverExpression, true);
            cachedLibrary.setDefaultExpression(receiverExpression);
            String receiverName = cachedLibrary.getParameter().getVariableElement().getSimpleName().toString();
            DSLExpression acceptGuard = new DSLExpression.Call(new DSLExpression.Variable(null, receiverName), "accepts", Arrays.asList(receiverExpression));
            acceptGuard = resolveCachedExpression(resolver, cachedLibrary, context.getType(boolean.class), acceptGuard, expression);
            if (acceptGuard != null) {
                GuardExpression guard = new GuardExpression(specialization, acceptGuard);
                guard.setLibraryAcceptsGuard(true);
                specialization.getGuards().add(guard);
            }
            TypeMirror libraryType = types.Library;
            TypeMirror usedLibraryType = parameterType;
            DSLExpression resolveCall = new DSLExpression.Call(null, "resolve", Arrays.asList(new DSLExpression.ClassLiteral(usedLibraryType)));
            DSLExpressionResolver cachedResolver = importStatics(resolver, types.LibraryFactory);
            DSLExpression defaultExpression = new DSLExpression.Call(resolveCall, "create", Arrays.asList(receiverExpression));
            defaultExpression = resolveCachedExpression(cachedResolver, cachedLibrary, libraryType, defaultExpression, expression);
            cachedLibrary.setDefaultExpression(defaultExpression);
            DSLExpression uncachedExpression = new DSLExpression.Call(resolveCall, "getUncached", Arrays.asList(receiverExpression));
            cachedLibrary.setUncachedExpression(uncachedExpression);
            uncachedExpression = resolveCachedExpression(cachedResolver, cachedLibrary, libraryType, uncachedExpression, expression);
            if (uncachedLibrary != null) {
                uncachedLibrary.setDefaultExpression(uncachedExpression);
                uncachedLibrary.setUncachedExpression(uncachedExpression);
                uncachedLibrary.setAlwaysInitialized(true);
                uncachedLibrary.setRequiresBoundary(true);
            }
        }
    }
    if (specialization.isFallback()) {
        for (int i = 0; i < libraries.size(); i++) {
            CacheExpression cachedLibrary = libraries.get(i);
            if (cachedLibrary.getCachedLibraryExpression() != null) {
                cachedLibrary.addError("@%s annotations with specialized receivers are not supported in combination with @%s annotations. " + "Specify the @%s(limit=\"...\") attribute and remove the receiver expression to use an dispatched library instead.", getSimpleName(types.CachedLibrary), getSimpleName(types.Fallback), getSimpleName(types.CachedLibrary));
            }
        }
    }
    if (!libraries.isEmpty() && !specialization.hasErrors() && ElementUtils.getAnnotationValue(specialization.getMarkerAnnotation(), "limit", false) == null && specialization.hasMultipleInstances()) {
        specialization.addError("The limit attribute must be specified if @%s is used with a dynamic parameter. E.g. add limit=\"3\" to resolve this.", types.CachedLibrary.asElement().getSimpleName().toString());
    }
    if (!seenDynamicParameterBound) {
        // bound by a cache only.
        return null;
    }
    return uncachedSpecialization;
}
Also used : LibraryParser(com.oracle.truffle.dsl.processor.library.LibraryParser) Variable(com.oracle.truffle.dsl.processor.expression.DSLExpression.Variable) VariableElement(javax.lang.model.element.VariableElement) CodeVariableElement(com.oracle.truffle.dsl.processor.java.model.CodeVariableElement) DSLExpression(com.oracle.truffle.dsl.processor.expression.DSLExpression) CacheExpression(com.oracle.truffle.dsl.processor.model.CacheExpression) ElementUtils.fromTypeMirror(com.oracle.truffle.dsl.processor.java.ElementUtils.fromTypeMirror) CodeTypeMirror(com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror) ArrayCodeTypeMirror(com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror) TypeMirror(javax.lang.model.type.TypeMirror) CodeVariableElement(com.oracle.truffle.dsl.processor.java.model.CodeVariableElement) Call(com.oracle.truffle.dsl.processor.expression.DSLExpression.Call) DSLExpressionResolver(com.oracle.truffle.dsl.processor.expression.DSLExpressionResolver) Variable(com.oracle.truffle.dsl.processor.expression.DSLExpression.Variable) Call(com.oracle.truffle.dsl.processor.expression.DSLExpression.Call) TypeElement(javax.lang.model.element.TypeElement) CodeTypeElement(com.oracle.truffle.dsl.processor.java.model.CodeTypeElement) GuardExpression(com.oracle.truffle.dsl.processor.model.GuardExpression) SpecializationData(com.oracle.truffle.dsl.processor.model.SpecializationData) LibraryData(com.oracle.truffle.dsl.processor.library.LibraryData) Cast(com.oracle.truffle.dsl.processor.expression.DSLExpression.Cast) Parameter(com.oracle.truffle.dsl.processor.model.Parameter) ClassLiteral(com.oracle.truffle.dsl.processor.expression.DSLExpression.ClassLiteral)

Aggregations

DSLExpression (com.oracle.truffle.dsl.processor.expression.DSLExpression)1 Call (com.oracle.truffle.dsl.processor.expression.DSLExpression.Call)1 Cast (com.oracle.truffle.dsl.processor.expression.DSLExpression.Cast)1 ClassLiteral (com.oracle.truffle.dsl.processor.expression.DSLExpression.ClassLiteral)1 Variable (com.oracle.truffle.dsl.processor.expression.DSLExpression.Variable)1 DSLExpressionResolver (com.oracle.truffle.dsl.processor.expression.DSLExpressionResolver)1 ElementUtils.fromTypeMirror (com.oracle.truffle.dsl.processor.java.ElementUtils.fromTypeMirror)1 CodeTypeElement (com.oracle.truffle.dsl.processor.java.model.CodeTypeElement)1 CodeTypeMirror (com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror)1 ArrayCodeTypeMirror (com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror)1 CodeVariableElement (com.oracle.truffle.dsl.processor.java.model.CodeVariableElement)1 LibraryData (com.oracle.truffle.dsl.processor.library.LibraryData)1 LibraryParser (com.oracle.truffle.dsl.processor.library.LibraryParser)1 CacheExpression (com.oracle.truffle.dsl.processor.model.CacheExpression)1 GuardExpression (com.oracle.truffle.dsl.processor.model.GuardExpression)1 Parameter (com.oracle.truffle.dsl.processor.model.Parameter)1 SpecializationData (com.oracle.truffle.dsl.processor.model.SpecializationData)1 TypeElement (javax.lang.model.element.TypeElement)1 VariableElement (javax.lang.model.element.VariableElement)1 TypeMirror (javax.lang.model.type.TypeMirror)1