Search in sources :

Example 1 with ElementUtils.isAssignable

use of com.oracle.truffle.dsl.processor.java.ElementUtils.isAssignable in project graal by oracle.

the class ExportsParser method parseExports.

private ExportsData parseExports(TypeElement type, List<AnnotationMirror> elementMirrors) {
    ExportsData model = new ExportsData(context, type, null);
    if (type.getKind().isInterface()) {
        model.addError("@%s is not supported for interfaces at the moment.", types.ExportLibrary.asElement().getSimpleName().toString());
        return model;
    }
    if (ElementUtils.getVisibility(type.getModifiers()) == Modifier.PRIVATE) {
        model.addError("The exported type must not be private. " + "Increase visibility to resolve this.");
        return model;
    }
    Map<AnnotationMirror, TypeElement> mirrors = new LinkedHashMap<>();
    for (AnnotationMirror annotationMirror : elementMirrors) {
        mirrors.put(annotationMirror, type);
    }
    TypeElement superType = type;
    while ((superType = getSuperType(superType)) != null) {
        for (AnnotationMirror mirror : getRepeatedAnnotation(superType.getAnnotationMirrors(), types.ExportLibrary)) {
            mirrors.put(mirror, superType);
        }
    }
    Map<String, List<AnnotationMirror>> mappedMirrors = new LinkedHashMap<>();
    for (AnnotationMirror mirror : mirrors.keySet()) {
        TypeMirror library = getAnnotationValue(TypeMirror.class, mirror, "value");
        mappedMirrors.computeIfAbsent(getTypeId(library), (id) -> new ArrayList<>()).add(mirror);
    }
    for (Entry<String, List<AnnotationMirror>> entry : mappedMirrors.entrySet()) {
        String libraryId = entry.getKey();
        List<AnnotationMirror> annotationMirrors = entry.getValue();
        AnnotationMirror annotationMirror = annotationMirrors.get(0);
        TypeMirror libraryMirror = getAnnotationValue(TypeMirror.class, annotationMirror, "value");
        AnnotationValue receiverClassValue = getAnnotationValue(annotationMirror, "receiverType");
        boolean explicitReceiver;
        TypeMirror receiverClass = getAnnotationValue(TypeMirror.class, annotationMirror, "receiverType", false);
        if (receiverClass == null) {
            explicitReceiver = false;
            receiverClass = type.asType();
        } else {
            explicitReceiver = true;
        }
        Map<TypeElement, LibraryData> libraryCache = ProcessorContext.getInstance().getCacheMap(LibraryParser.class);
        LibraryData libraryData = libraryCache.computeIfAbsent(fromTypeMirror(libraryMirror), (t) -> new LibraryParser().parse(t));
        ExportsLibrary lib = new ExportsLibrary(context, type, annotationMirror, model, libraryData, receiverClass, explicitReceiver);
        ExportsLibrary otherLib = model.getExportedLibraries().get(libraryId);
        for (AnnotationMirror mirror : annotationMirrors) {
            lib.getDeclaringTypes().add(mirrors.get(mirror));
        }
        model.getExportedLibraries().put(libraryId, lib);
        Integer priority = getAnnotationValue(Integer.class, annotationMirror, "priority", false);
        if (priority == null && lib.needsDefaultExportProvider()) {
            lib.addError(// 
            "The priority property must be set for default exports based on service providers. " + "See @%s(priority=...) for details.", getSimpleName(types.ExportLibrary));
            continue;
        } else if (priority != null) {
            int prio = priority;
            AnnotationValue annotationValue = getAnnotationValue(annotationMirror, "priority");
            if (prio < 0) {
                LibraryDefaultExportData builtinDefaultExport = libraryData.getBuiltinDefaultExport(receiverClass);
                if (builtinDefaultExport != null) {
                    lib.addError(annotationValue, // 
                    "The provided export receiver type '%s' is not reachable with the given priority. " + // 
                    "The '%s' library specifies @%s(%s) which has receiver type '%s' and that shadows this export. " + "Increase the priority to a positive integer to resolve this.", getSimpleName(receiverClass), getSimpleName(libraryData.getTemplateType()), getSimpleName(types.GenerateLibrary_DefaultExport), getSimpleName(builtinDefaultExport.getImplType()), getSimpleName(builtinDefaultExport.getReceiverType()));
                    continue;
                }
            }
            if (prio == 0) {
                lib.addError(annotationValue, "The set priority must be either positive or negative, but must not be 0.");
                continue;
            }
            lib.setDefaultExportPriority(priority);
        }
        if (ElementUtils.isPrimitive(receiverClass)) {
            lib.addError(annotationMirror, receiverClassValue, "Primitive receiver types are not supported yet.");
            continue;
        }
        if (libraryData == null) {
            lib.addError("Class '%s' is not a library annotated with @%s.", getSimpleName(libraryMirror), types.GenerateLibrary.asElement().getSimpleName().toString());
            continue;
        } else if (libraryData.hasErrors()) {
            lib.addError("Library specification %s has errors. Please resolve them first.", getSimpleName(libraryMirror));
            continue;
        }
        if (otherLib != null) {
            String message = String.format("Duplicate library specified %s.", getSimpleName(libraryMirror));
            otherLib.addError(message);
            lib.addError(message);
            continue;
        }
        lib.setUseForAOT(ElementUtils.getAnnotationValue(Boolean.class, annotationMirror, "useForAOT"));
        if (libraryData.isGenerateAOT()) {
            AnnotationValue useForAOT = getAnnotationValue(annotationMirror, "useForAOT", false);
            if (useForAOT == null) {
                lib.addError(annotationMirror, useForAOT, // 
                "The useForAOT property needs to be declared for exports of libraries annotated with @%s. " + "Declare the useForAOT property to resolve this problem.", getSimpleName(types.GenerateAOT));
            }
            Integer useForAOTPriority = getAnnotationValue(Integer.class, annotationMirror, "useForAOTPriority", false);
            if (useForAOTPriority == null && lib.isUseForAOT()) {
                lib.addError(// 
                "The useForAOTPriority property must also be set for libraries used for AOT. " + "See @%s(useForAOTPriority=...) for details.", getSimpleName(types.ExportLibrary));
                continue;
            } else if (useForAOTPriority != null) {
                lib.setUseForAOTPriority(useForAOTPriority);
            }
        }
        if (lib.isUseForAOT() && !lib.isFinalReceiver()) {
            AnnotationValue useForAOT = getAnnotationValue(annotationMirror, "useForAOT", false);
            lib.addError(annotationMirror, useForAOT, // 
            "If useForAOT is set to true the receiver type must be a final. " + // 
            "The compiled code would otherwise cause performance warnings. " + "Add the final modifier to the receiver class or set useForAOT to false to resolve this.");
        } else if (lib.isUseForAOT() && lib.isDynamicDispatchTarget()) {
            AnnotationMirror dynamicDispatchExportMirror = lib.getReceiverDynamicDispatchExport();
            if (dynamicDispatchExportMirror == null) {
                throw new AssertionError("Should not reach here. isDynamicDispatchTarget should not return true");
            }
            if (!ElementUtils.getAnnotationValue(Boolean.class, dynamicDispatchExportMirror, "useForAOT")) {
                AnnotationValue useForAOT = getAnnotationValue(annotationMirror, "useForAOT", false);
                lib.addError(annotationMirror, useForAOT, "The dynamic dispatch target must set useForAOT to true also for the DynamicDispatch export of the receiver type %s. ", getSimpleName(lib.getReceiverType()));
            }
        }
        if (lib.isUseForAOT() && !libraryData.isGenerateAOT() && !libraryData.isDynamicDispatch()) {
            AnnotationValue useForAOT = getAnnotationValue(annotationMirror, "useForAOT", false);
            lib.addError(annotationMirror, useForAOT, "The exported library does not support AOT. Add the @%s annotation to the library class %s to resolve this.", getSimpleName(types.GenerateAOT), getQualifiedName(libraryData.getTemplateType()));
        }
        if (explicitReceiver) {
            TypeMirror receiverTypeErasure = context.getEnvironment().getTypeUtils().erasure(libraryData.getSignatureReceiverType());
            if (!isSubtype(receiverClass, receiverTypeErasure)) {
                lib.addError(annotationMirror, receiverClassValue, "The export receiver type %s is not compatible with the library receiver type '%s' of library '%s'. ", getSimpleName(receiverClass), getSimpleName(libraryData.getSignatureReceiverType()), getSimpleName(libraryData.getTemplateType().asType()));
            }
        } else {
            if (!isSubtype(type.asType(), libraryData.getExportsReceiverType())) {
                lib.addError("Type %s is not compatible with the receiver type '%s' of exported library '%s'. " + "Inhert from type '%s' to resolve this.", getSimpleName(type.asType()), getSimpleName(libraryData.getExportsReceiverType()), getSimpleName(libraryData.getTemplateType().asType()), getSimpleName(libraryData.getExportsReceiverType()));
            }
        }
        String transitionLimit = ElementUtils.getAnnotationValue(String.class, annotationMirror, "transitionLimit", false);
        if (transitionLimit != null) {
            DSLExpressionResolver resolver = new DSLExpressionResolver(context, model.getTemplateType(), NodeParser.importVisibleStaticMembers(model.getTemplateType(), model.getTemplateType(), false));
            try {
                DSLExpression expression = DSLExpression.parse(transitionLimit);
                expression.accept(resolver);
                lib.setTransitionLimit(expression);
            } catch (InvalidExpressionException e) {
                AnnotationValue allowTransition = ElementUtils.getAnnotationValue(annotationMirror, "transitionLimit");
                model.addError(annotationMirror, allowTransition, "Error parsing expression '%s': %s", transitionLimit, e.getMessage());
            }
        }
        String delegateTo = ElementUtils.getAnnotationValue(String.class, annotationMirror, "delegateTo", false);
        if (delegateTo != null) {
            AnnotationValue delegateToValue = ElementUtils.getAnnotationValue(annotationMirror, "delegateTo");
            if (receiverClass.getKind() != TypeKind.DECLARED) {
                lib.addError(delegateToValue, "The receiver type must be declared type for delegation.");
                continue;
            }
            VariableElement delegateVar = ElementUtils.findVariableElement((DeclaredType) receiverClass, delegateTo);
            if (delegateVar == null) {
                lib.addError(delegateToValue, "The delegation variable with name '%s' could not be found in type '%s'. " + "Declare a field 'final Object %s' in '%s' to resolve this problem.", delegateTo, ElementUtils.getSimpleName(receiverClass), delegateTo, ElementUtils.getSimpleName(receiverClass));
                continue;
            }
            if (!delegateVar.getModifiers().contains(Modifier.FINAL)) {
                lib.addError(delegateToValue, "The delegation variable with name '%s' in type '%s' must be have the modifier final. " + "Make the variable final to resolve the problem.", delegateTo, ElementUtils.getSimpleName(receiverClass));
                continue;
            }
            Element packageElement = ElementUtils.findPackageElement(lib.getTemplateType());
            if (!ElementUtils.isVisible(packageElement, delegateVar)) {
                lib.addError(delegateToValue, "The delegation variable with name '%s' in type '%s' is not visible in package '%s'. " + "Increase the visibility to resolve this problem.", delegateTo, ElementUtils.getSimpleName(receiverClass), ElementUtils.getPackageName(packageElement));
                continue;
            }
            TypeMirror delegateType = delegateVar.asType();
            TypeMirror exportsReceiverType = lib.getLibrary().getSignatureReceiverType();
            if (!ElementUtils.isAssignable(delegateType, exportsReceiverType)) {
                lib.addError(delegateToValue, "The type of export delegation field '%s' is not assignable to the expected type '%s'. " + "Change the field type to '%s' to resolve this.", ElementUtils.getSimpleName(receiverClass) + "." + delegateTo, ElementUtils.getSimpleName(exportsReceiverType), ElementUtils.getSimpleName(exportsReceiverType));
                continue;
            }
            lib.setDelegationVariable(delegateVar);
        }
        for (LibraryMessage message : libraryData.getMethods()) {
            model.getLibraryMessages().computeIfAbsent(message.getName(), (n) -> new ArrayList<>()).add(message);
        }
    }
    // initialize dynamic dispatch
    for (ExportsLibrary exportedLibrary : model.getExportedLibraries().values()) {
        if (exportedLibrary.hasErrors()) {
            continue;
        }
        boolean explicitReceiver = exportedLibrary.isExplicitReceiver();
        int dynamicDispatchEnabledCount = 0;
        for (ExportsLibrary library : model.getExportedLibraries().values()) {
            if (library.getLibrary().isDynamicDispatchEnabled()) {
                dynamicDispatchEnabledCount++;
            }
        }
        if (exportedLibrary.getLibrary().isDynamicDispatch() && dynamicDispatchEnabledCount > 0) {
            exportedLibrary.addError("@%s cannot be used for other libraries if the %s library is exported. " + "Using dynamic dispatch and other libraries is mutually exclusive. " + "To resolve this use the dynamic dispatch mechanism of the receiver type instead to export libraries.", types.ExportLibrary.asElement().getSimpleName().toString(), types.DynamicDispatchLibrary.asElement().getSimpleName().toString());
        } else if (explicitReceiver && !exportedLibrary.getLibrary().isDefaultExportLookupEnabled() && !exportedLibrary.isDynamicDispatchTarget() && !exportedLibrary.isBuiltinDefaultExport()) {
            String dynamicDispatchDisabled = "";
            if (!exportedLibrary.getLibrary().isDynamicDispatchEnabled()) {
                dynamicDispatchDisabled = String.format("Note that dynamic dispatch is disabled for the exported library '%s'.%n", ElementUtils.getSimpleName(exportedLibrary.getLibrary().getTemplateType()));
            }
            // 
            exportedLibrary.addError(// 
            exportedLibrary.getTemplateTypeAnnotation(), getAnnotationValue(exportedLibrary.getTemplateTypeAnnotation(), "receiverType"), "Using explicit receiver types is only supported for default exports or types that export %s.%n" + // dynamic dispatch disabled
            "%s" + "To resolve this use one of the following strategies:%n" + "  - Make the receiver type implicit by applying '@%s(%s.class)' to the receiver type '%s' instead.%n" + "  - Declare a default export on the '%s' library with '@%s(%s.class)'%n" + "  - Enable default exports with service providers using @%s(defaultExportLookupEnabled=true) on the library and specify an export priority%n" + "  - Enable dynamic dispatch by annotating the receiver type with '@%s(%s.class)'.", types.DynamicDispatchLibrary.asElement().getSimpleName().toString(), dynamicDispatchDisabled, types.ExportLibrary.asElement().getSimpleName().toString(), exportedLibrary.getLibrary().getTemplateType().getSimpleName().toString(), ElementUtils.getSimpleName(exportedLibrary.getExplicitReceiver()), exportedLibrary.getLibrary().getTemplateType().getSimpleName().toString(), types.GenerateLibrary_DefaultExport.asElement().getSimpleName().toString(), ElementUtils.getSimpleName(exportedLibrary.getTemplateType().asType()), ElementUtils.getSimpleName(types.GenerateLibrary), types.ExportLibrary.asElement().getSimpleName().toString(), types.DynamicDispatchLibrary.asElement().getSimpleName().toString());
        } else {
            if (explicitReceiver && !exportedLibrary.isBuiltinDefaultExport()) {
                boolean foundInvalidExportsOnReceiver = false;
                superType = ElementUtils.castTypeElement(exportedLibrary.getExplicitReceiver());
                while (superType != null) {
                    List<AnnotationMirror> exports = getRepeatedAnnotation(superType.getAnnotationMirrors(), types.ExportLibrary);
                    for (AnnotationMirror export : exports) {
                        TypeMirror exportedLibraryType = getAnnotationValue(TypeMirror.class, export, "value");
                        if (!ElementUtils.typeEquals(exportedLibraryType, types.DynamicDispatchLibrary)) {
                            foundInvalidExportsOnReceiver = true;
                            break;
                        }
                    }
                    superType = getSuperType(superType);
                }
                if (foundInvalidExportsOnReceiver) {
                    AnnotationValue receiverClassValue = getAnnotationValue(exportedLibrary.getMessageAnnotation(), "receiverType");
                    exportedLibrary.addError(exportedLibrary.getMessageAnnotation(), receiverClassValue, "An export that is used for dynamic dispatch must not export any libraries other than %s with the receiver type.", types.DynamicDispatchLibrary.asElement().getSimpleName().toString());
                    continue;
                }
            }
        }
    }
    return model;
}
Also used : Arrays(java.util.Arrays) Modifier(javax.lang.model.element.Modifier) TypeElement(javax.lang.model.element.TypeElement) ElementUtils.getRepeatedAnnotation(com.oracle.truffle.dsl.processor.java.ElementUtils.getRepeatedAnnotation) ElementUtils.getSimpleName(com.oracle.truffle.dsl.processor.java.ElementUtils.getSimpleName) ElementUtils.getQualifiedName(com.oracle.truffle.dsl.processor.java.ElementUtils.getQualifiedName) Map(java.util.Map) ElementUtils.getTypeId(com.oracle.truffle.dsl.processor.java.ElementUtils.getTypeId) CodeVariableElement(com.oracle.truffle.dsl.processor.java.model.CodeVariableElement) ElementUtils.firstLetterUpperCase(com.oracle.truffle.dsl.processor.java.ElementUtils.firstLetterUpperCase) NodeData(com.oracle.truffle.dsl.processor.model.NodeData) CodeExecutableElement(com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement) ElementUtils.getSuperType(com.oracle.truffle.dsl.processor.java.ElementUtils.getSuperType) CodeTypeElement(com.oracle.truffle.dsl.processor.java.model.CodeTypeElement) Predicate(java.util.function.Predicate) Collection(java.util.Collection) Set(java.util.Set) Element(javax.lang.model.element.Element) Collectors(java.util.stream.Collectors) TypeKind(javax.lang.model.type.TypeKind) List(java.util.List) Entry(java.util.Map.Entry) ElementUtils.isAssignable(com.oracle.truffle.dsl.processor.java.ElementUtils.isAssignable) AnnotationValue(javax.lang.model.element.AnnotationValue) DSLExpression(com.oracle.truffle.dsl.processor.expression.DSLExpression) NodeParser(com.oracle.truffle.dsl.processor.parser.NodeParser) VariableElement(javax.lang.model.element.VariableElement) HashMap(java.util.HashMap) ElementUtils.fromTypeMirror(com.oracle.truffle.dsl.processor.java.ElementUtils.fromTypeMirror) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) LinkedHashMap(java.util.LinkedHashMap) ElementUtils.findAnnotationMirror(com.oracle.truffle.dsl.processor.java.ElementUtils.findAnnotationMirror) CompilerFactory(com.oracle.truffle.dsl.processor.java.compiler.CompilerFactory) ElementUtils.isSubtype(com.oracle.truffle.dsl.processor.java.ElementUtils.isSubtype) ElementUtils.typeEquals(com.oracle.truffle.dsl.processor.java.ElementUtils.typeEquals) DeclaredType(javax.lang.model.type.DeclaredType) InvalidExpressionException(com.oracle.truffle.dsl.processor.expression.InvalidExpressionException) ElementUtils.getAnnotationValue(com.oracle.truffle.dsl.processor.java.ElementUtils.getAnnotationValue) GeneratorUtils(com.oracle.truffle.dsl.processor.generator.GeneratorUtils) ElementFilter(javax.lang.model.util.ElementFilter) LinkedHashSet(java.util.LinkedHashSet) ElementUtils(com.oracle.truffle.dsl.processor.java.ElementUtils) AbstractParser(com.oracle.truffle.dsl.processor.parser.AbstractParser) CodeAnnotationMirror(com.oracle.truffle.dsl.processor.java.model.CodeAnnotationMirror) Iterator(java.util.Iterator) ElementKind(javax.lang.model.element.ElementKind) ElementUtils.elementEquals(com.oracle.truffle.dsl.processor.java.ElementUtils.elementEquals) PUBLIC(javax.lang.model.element.Modifier.PUBLIC) ExecutableElement(javax.lang.model.element.ExecutableElement) ProcessorContext(com.oracle.truffle.dsl.processor.ProcessorContext) CodeAnnotationValue(com.oracle.truffle.dsl.processor.java.model.CodeAnnotationValue) AnnotationMirror(javax.lang.model.element.AnnotationMirror) CodeNames(com.oracle.truffle.dsl.processor.java.model.CodeNames) STATIC(javax.lang.model.element.Modifier.STATIC) TypeMirror(javax.lang.model.type.TypeMirror) ElementUtils.modifiers(com.oracle.truffle.dsl.processor.java.ElementUtils.modifiers) ElementUtils.firstLetterLowerCase(com.oracle.truffle.dsl.processor.java.ElementUtils.firstLetterLowerCase) Collections(java.util.Collections) DSLExpressionResolver(com.oracle.truffle.dsl.processor.expression.DSLExpressionResolver) TypeElement(javax.lang.model.element.TypeElement) CodeVariableElement(com.oracle.truffle.dsl.processor.java.model.CodeVariableElement) CodeExecutableElement(com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement) CodeTypeElement(com.oracle.truffle.dsl.processor.java.model.CodeTypeElement) Element(javax.lang.model.element.Element) VariableElement(javax.lang.model.element.VariableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) ArrayList(java.util.ArrayList) CodeVariableElement(com.oracle.truffle.dsl.processor.java.model.CodeVariableElement) VariableElement(javax.lang.model.element.VariableElement) DSLExpression(com.oracle.truffle.dsl.processor.expression.DSLExpression) LinkedHashMap(java.util.LinkedHashMap) ElementUtils.fromTypeMirror(com.oracle.truffle.dsl.processor.java.ElementUtils.fromTypeMirror) TypeMirror(javax.lang.model.type.TypeMirror) InvalidExpressionException(com.oracle.truffle.dsl.processor.expression.InvalidExpressionException) List(java.util.List) ArrayList(java.util.ArrayList) DSLExpressionResolver(com.oracle.truffle.dsl.processor.expression.DSLExpressionResolver) TypeElement(javax.lang.model.element.TypeElement) CodeTypeElement(com.oracle.truffle.dsl.processor.java.model.CodeTypeElement) ElementUtils.findAnnotationMirror(com.oracle.truffle.dsl.processor.java.ElementUtils.findAnnotationMirror) CodeAnnotationMirror(com.oracle.truffle.dsl.processor.java.model.CodeAnnotationMirror) AnnotationMirror(javax.lang.model.element.AnnotationMirror) AnnotationValue(javax.lang.model.element.AnnotationValue) ElementUtils.getAnnotationValue(com.oracle.truffle.dsl.processor.java.ElementUtils.getAnnotationValue) CodeAnnotationValue(com.oracle.truffle.dsl.processor.java.model.CodeAnnotationValue)

Example 2 with ElementUtils.isAssignable

use of com.oracle.truffle.dsl.processor.java.ElementUtils.isAssignable in project graal by oracle.

the class FlatNodeGenFactory method generateAOT.

private void generateAOT(CodeTypeElement clazz) {
    TypeMirror aotProviderType = new GeneratedTypeMirror(ElementUtils.getPackageName(types.GenerateAOT_Provider), "GenerateAOT.Provider");
    clazz.getImplements().add(aotProviderType);
    CodeExecutableElement prepare = clazz.add(CodeExecutableElement.cloneNoAnnotations(ElementUtils.findMethod(types.GenerateAOT_Provider, "prepareForAOT")));
    prepare.renameArguments("language", "root");
    GeneratorUtils.addOverride(prepare);
    prepare.getModifiers().remove(ABSTRACT);
    CodeTreeBuilder builder = prepare.createBuilder();
    List<SpecializationData> filteredSpecializations = new ArrayList<>();
    for (NodeData currentNode : sharingNodes) {
        for (SpecializationData s : calculateReachableSpecializations(currentNode)) {
            if (s.getMethod() == null || !s.isPrepareForAOT()) {
                continue;
            }
            filteredSpecializations.add(s);
        }
    }
    FrameState frameState = FrameState.load(this, NodeExecutionMode.SLOW_PATH, prepare);
    frameState.setBoolean(AOT_STATE, true);
    Map<StateBitSet, List<SpecializationData>> stateGroup = new LinkedHashMap<>();
    Set<TypeGuard> implicitCasts = new LinkedHashSet<>();
    for (SpecializationData specialization : filteredSpecializations) {
        for (StateBitSet set : allMultiState.getSets()) {
            if (set.contains(AOT_PREPARED)) {
                // make sure we have an entry for a state bitset
                // without any specialization but only with the AOT bit set
                stateGroup.computeIfAbsent(set, (s) -> new ArrayList<>());
            }
            if (set.contains(specialization)) {
                stateGroup.computeIfAbsent(set, (s) -> new ArrayList<>()).add(specialization);
                break;
            }
        }
        int index = 0;
        for (Parameter p : specialization.getSignatureParameters()) {
            TypeMirror targetType = p.getType();
            Collection<TypeMirror> sourceTypes = node.getTypeSystem().lookupSourceTypes(targetType);
            if (sourceTypes.size() > 1) {
                implicitCasts.add(new TypeGuard(targetType, index));
            }
            index++;
        }
    }
    builder.startAssert();
    builder.string("!isAdoptable() || ");
    builder.string("(").cast(context.getType(ReentrantLock.class), CodeTreeBuilder.singleString("getLock()"));
    builder.string(").isHeldByCurrentThread()");
    builder.string(" : ").doubleQuote("During prepare AST lock must be held.");
    builder.end();
    builder.tree(multiState.createLoad(frameState, AOT_PREPARED));
    builder.tree(multiState.createLoad(frameState, filteredSpecializations.toArray()));
    for (StateBitSet set : multiState.getSets()) {
        if (set.contains(AOT_PREPARED)) {
            builder.startIf();
            builder.tree(set.createContains(frameState, AOT_PREPARED));
            builder.end().startBlock();
            builder.returnDefault();
            builder.end();
            break;
        }
    }
    List<Object> bulkStateSet = new ArrayList<>();
    Set<String> languagesChecked = new HashSet<>();
    for (SpecializationData specialization : filteredSpecializations) {
        // we need to copy otherwise local variables of caches may conflict.
        FrameState innerFrameState = frameState.copy();
        SpecializationGroup specializationGroup = SpecializationGroup.create(Arrays.asList(specialization));
        for (CacheExpression cache : specialization.getCaches()) {
            if (!cache.isAlwaysInitialized()) {
                continue;
            }
            setCacheInitialized(innerFrameState, specialization, cache, true);
        }
        List<IfTriple> tripples = new ArrayList<>();
        for (AssumptionExpression assumption : specialization.getAssumptionExpressions()) {
            tripples.addAll(createAssumptionSlowPathTriples(innerFrameState, specializationGroup, assumption));
        }
        /*
             * We don't need to materialize assumption conditions.
             */
        for (IfTriple triple : tripples) {
            triple.condition = null;
        }
        // compute guards that can be materialized
        List<GuardExpression> usedGuards = new ArrayList<>();
        for (GuardExpression guard : specialization.getGuards()) {
            if (guardNeedsStateBit(specialization, guard)) {
                bulkStateSet.add(guard);
            }
            if (specialization.isDynamicParameterBound(guard.getExpression(), true)) {
                if (!specialization.isOnlyLanguageReferencesBound(guard.getExpression())) {
                    /*
                         * Guards with only language references can be executed.
                         */
                    continue;
                }
            }
            usedGuards.add(guard);
        }
        for (CacheExpression cache : specialization.getCaches()) {
            if (!cache.isAlwaysInitialized()) {
                continue;
            }
            if (cache.isCachedLanguage()) {
                boolean needsLocal = false;
                for (GuardExpression guard : usedGuards) {
                    if (specialization.isExpressionBindsCache(guard.getExpression(), cache)) {
                        needsLocal = true;
                        break;
                    }
                }
                if (!needsLocal) {
                    for (CacheExpression otherCache : specialization.getCaches()) {
                        if (cache == otherCache) {
                            continue;
                        }
                        if (specialization.isExpressionBindsCache(otherCache.getDefaultExpression(), cache)) {
                            needsLocal = true;
                            break;
                        }
                    }
                }
                TypeMirror languageType = cache.getLanguageType();
                boolean needsCheck = false;
                if (!usedGuards.isEmpty()) {
                    needsCheck = languagesChecked.add(ElementUtils.getTypeId(languageType));
                }
                CodeTreeBuilder b = builder.create();
                if (needsCheck) {
                    b.startIf().string("language == null || language.getClass() != ").typeLiteral(languageType).end().startBlock();
                    b.startStatement().startStaticCall(types.CompilerDirectives, "transferToInterpreterAndInvalidate").end().end();
                    b.startThrow().startStaticCall(types.CompilerDirectives, "shouldNotReachHere");
                    b.startStaticCall(context.getType(String.class), "format");
                    b.doubleQuote(String.format("Specialization '%s' in node class '%s' is enabled for AOT generation. " + "The specialization declares a @%s for language class %s but was prepared for AOT with language class '%%s'. " + "Match the language used in the language reference or exclude the specialization from AOT generation with @%s.%s to resolve this problem.", getReadableSignature(specialization.getMethod()), getQualifiedName(specialization.getNode().getTemplateType()), getSimpleName(types.CachedLanguage), getQualifiedName(cache.getLanguageType()), getSimpleName(types.GenerateAOT), getSimpleName(types.GenerateAOT_Exclude)));
                    b.string("language != null ? language.getClass().getName() : \"null\"");
                    b.end();
                    // static call, throw,
                    b.end().end();
                    // if block
                    b.end();
                }
                if (needsLocal) {
                    b.startStatement();
                    b.type(languageType);
                    b.string(" ", createCacheLocalName(specialization, cache));
                    b.string(" = ").maybeCast(types.TruffleLanguage, cache.getLanguageType(), "language");
                    // statement
                    b.end();
                }
                tripples.add(new IfTriple(b.build(), null, null));
            }
        }
        for (GuardExpression guard : usedGuards) {
            Set<CacheExpression> caches = specialization.getBoundCaches(guard.getExpression(), true);
            tripples.addAll(initializeCaches(innerFrameState, NodeExecutionMode.SLOW_PATH, specializationGroup, caches, true, false));
            tripples.add(createMethodGuardCheck(innerFrameState, specialization, guard, NodeExecutionMode.SLOW_PATH));
        }
        BlockState state = IfTriple.materialize(builder, tripples, false);
        builder.tree(createSpecialize(builder, innerFrameState, specializationGroup, specialization, true));
        for (CacheExpression cache : specialization.getCaches()) {
            if (cache.isAlwaysInitialized()) {
                continue;
            }
            /*
                 * Libraries might not be AOT preparable. E.g. if a cached library was created from
                 * a final field of the current language. In such a case we should just not call
                 * prepareForAOT.
                 *
                 * Specializable nodes are always known to be preparable if they reach the code
                 * generator.
                 */
            boolean cachedLibrary = cache.isCachedLibrary();
            if (cachedLibrary) {
                builder.startIf().tree(createCacheReference(innerFrameState, specialization, cache)).instanceOf(aotProviderType).end().startBlock();
            }
            if (NodeCodeGenerator.isSpecializedNode(cache.getParameter().getType()) || cachedLibrary) {
                builder.startAssert().startStaticCall(types.NodeUtil, "assertRecursion");
                builder.tree(createCacheReference(innerFrameState, specialization, cache));
                /*
                     * We allow a single recursion level only for AOT preparation. It is important
                     * that we only assert recursion for @Cached fields as regular AST children can
                     * be recursive arbitrarily deep.
                     *
                     * We might need to increase this limit in the future if it triggers to eagerly.
                     */
                builder.string("1");
                builder.end().end();
                builder.startStatement();
                builder.string("(");
                builder.cast(aotProviderType);
                builder.tree(createCacheReference(innerFrameState, specialization, cache));
                builder.string(")");
                builder.string(".prepareForAOT(language, root)");
                builder.end();
            }
            if (cachedLibrary) {
                builder.end();
            }
        }
        if (usedGuards.isEmpty()) {
            bulkStateSet.add(specialization);
        } else {
            builder.tree(multiState.createSet(innerFrameState, new SpecializationData[] { specialization }, true, false));
        }
        builder.end(state.blockCount);
    }
    List<Object> allElements = new ArrayList<>();
    allElements.add(AOT_PREPARED);
    allElements.addAll(bulkStateSet);
    allElements.addAll(implicitCasts);
    builder.tree(multiState.createSet(frameState, allElements.toArray(), true, true));
    if (!needsAOTReset()) {
        return;
    }
    CodeExecutableElement reset = clazz.add(new CodeExecutableElement(modifiers(PRIVATE), context.getType(void.class), "resetAOT_"));
    frameState = FrameState.load(this, NodeExecutionMode.FAST_PATH, reset);
    reset.getModifiers().remove(ABSTRACT);
    builder = reset.createBuilder();
    for (StateBitSet set : multiState.all) {
        if (set.contains(AOT_PREPARED)) {
            builder.tree(set.createLoad(frameState));
            builder.startIf();
            builder.tree(set.createNotContains(frameState, AOT_PREPARED));
            builder.end().startBlock();
            builder.returnDefault();
            builder.end();
        }
        break;
    }
    for (SpecializationData specialization : filteredSpecializations) {
        List<CacheExpression> resetCaches = new ArrayList<>();
        for (CacheExpression cache : specialization.getCaches()) {
            if (cache.isAlwaysInitialized()) {
                continue;
            }
            if (types.Profile != null && ElementUtils.isAssignable(cache.getParameter().getType(), types.Profile)) {
                resetCaches.add(cache);
            }
        }
        if (resetCaches.size() > 0) {
            builder.tree(multiState.createLoadAll(frameState, specialization));
            builder.startIf().tree(multiState.createContainsAll(frameState, new Object[] { specialization })).end();
            builder.startBlock();
            for (CacheExpression cache : resetCaches) {
                builder.startStatement();
                builder.tree(createCacheReference(frameState, specialization, cache));
                builder.string(".reset()");
                builder.end();
            }
            builder.end();
        }
    }
    for (StateBitSet set : multiState.getSets()) {
        builder.tree(set.createSetZero(frameState, true));
    }
    if (requiresExclude()) {
        builder.tree(exclude.createSetZero(frameState, true));
    }
    /*
         * It is important that we reset the state first before we clear the caches for initialized
         * libraries. Otherwise we might observe an enabled specialization without initialized cache
         * on the fast-path.
         */
    for (SpecializationData specialization : filteredSpecializations) {
        boolean resetSpecializationClass = false;
        for (CacheExpression cache : specialization.getCaches()) {
            if (cache.isAlwaysInitialized()) {
                continue;
            }
            if (cache.isCachedLibraryManuallyDispatched()) {
                if (useSpecializationClass(specialization)) {
                    resetSpecializationClass = true;
                    break;
                }
                builder.startStatement();
                builder.tree(createCacheReference(frameState, specialization, cache)).string(" = null");
                builder.end();
            }
        }
        if (resetSpecializationClass || specialization.hasMultipleInstances()) {
            builder.startStatement();
            builder.string("this.", createSpecializationFieldName(specialization));
            builder.string(" = null");
            builder.end();
        }
    }
}
Also used : LinkedHashSet(java.util.LinkedHashSet) Arrays(java.util.Arrays) Modifier(javax.lang.model.element.Modifier) Parameter(com.oracle.truffle.dsl.processor.model.Parameter) AssumptionExpression(com.oracle.truffle.dsl.processor.model.AssumptionExpression) TypeElement(javax.lang.model.element.TypeElement) ElementUtils.isObject(com.oracle.truffle.dsl.processor.java.ElementUtils.isObject) CreateCastData(com.oracle.truffle.dsl.processor.model.CreateCastData) CodeTypeParameterElement(com.oracle.truffle.dsl.processor.java.model.CodeTypeParameterElement) ElementUtils.uniqueSortedTypes(com.oracle.truffle.dsl.processor.java.ElementUtils.uniqueSortedTypes) NodeFieldData(com.oracle.truffle.dsl.processor.model.NodeFieldData) DSLExpressionReducer(com.oracle.truffle.dsl.processor.expression.DSLExpression.DSLExpressionReducer) FINAL(javax.lang.model.element.Modifier.FINAL) ImplicitCastData(com.oracle.truffle.dsl.processor.model.ImplicitCastData) Map(java.util.Map) ElementUtils.getTypeId(com.oracle.truffle.dsl.processor.java.ElementUtils.getTypeId) ElementUtils.firstLetterUpperCase(com.oracle.truffle.dsl.processor.java.ElementUtils.firstLetterUpperCase) ArrayType(javax.lang.model.type.ArrayType) ClassLiteral(com.oracle.truffle.dsl.processor.expression.DSLExpression.ClassLiteral) CodeExecutableElement(com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement) ElementUtils.setVisibility(com.oracle.truffle.dsl.processor.java.ElementUtils.setVisibility) Set(java.util.Set) Element(javax.lang.model.element.Element) GuardExpression(com.oracle.truffle.dsl.processor.model.GuardExpression) SpecializationGroup(com.oracle.truffle.dsl.processor.parser.SpecializationGroup) NodeChildData(com.oracle.truffle.dsl.processor.model.NodeChildData) ElementUtils.isAssignable(com.oracle.truffle.dsl.processor.java.ElementUtils.isAssignable) DSLExpression(com.oracle.truffle.dsl.processor.expression.DSLExpression) ElementUtils.boxType(com.oracle.truffle.dsl.processor.java.ElementUtils.boxType) GeneratorUtils.createTransferToInterpreterAndInvalidate(com.oracle.truffle.dsl.processor.generator.GeneratorUtils.createTransferToInterpreterAndInvalidate) AbstractDSLExpressionVisitor(com.oracle.truffle.dsl.processor.expression.DSLExpression.AbstractDSLExpressionVisitor) VariableElement(javax.lang.model.element.VariableElement) TruffleTypes(com.oracle.truffle.dsl.processor.TruffleTypes) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) ElementUtils.findAnnotationMirror(com.oracle.truffle.dsl.processor.java.ElementUtils.findAnnotationMirror) ElementUtils.getVisibility(com.oracle.truffle.dsl.processor.java.ElementUtils.getVisibility) CacheExpression(com.oracle.truffle.dsl.processor.model.CacheExpression) SpecializationThrowsData(com.oracle.truffle.dsl.processor.model.SpecializationThrowsData) DeclaredType(javax.lang.model.type.DeclaredType) ElementFilter(javax.lang.model.util.ElementFilter) LinkedHashSet(java.util.LinkedHashSet) Variable(com.oracle.truffle.dsl.processor.expression.DSLExpression.Variable) ElementUtils.needsCastTo(com.oracle.truffle.dsl.processor.java.ElementUtils.needsCastTo) VarHandle(java.lang.invoke.VarHandle) ProcessorContext(com.oracle.truffle.dsl.processor.ProcessorContext) CodeAnnotationValue(com.oracle.truffle.dsl.processor.java.model.CodeAnnotationValue) AnnotationMirror(javax.lang.model.element.AnnotationMirror) CodeNames(com.oracle.truffle.dsl.processor.java.model.CodeNames) Lock(java.util.concurrent.locks.Lock) CodeTree(com.oracle.truffle.dsl.processor.java.model.CodeTree) Negate(com.oracle.truffle.dsl.processor.expression.DSLExpression.Negate) ExportsGenerator(com.oracle.truffle.dsl.processor.library.ExportsGenerator) ExecutableTypeData(com.oracle.truffle.dsl.processor.model.ExecutableTypeData) ListIterator(java.util.ListIterator) TypeGuard(com.oracle.truffle.dsl.processor.parser.SpecializationGroup.TypeGuard) ElementUtils.getReadableSignature(com.oracle.truffle.dsl.processor.java.ElementUtils.getReadableSignature) CodeTreeBuilder(com.oracle.truffle.dsl.processor.java.model.CodeTreeBuilder) ElementUtils.getSimpleName(com.oracle.truffle.dsl.processor.java.ElementUtils.getSimpleName) NodeExecutionData(com.oracle.truffle.dsl.processor.model.NodeExecutionData) ElementUtils.getQualifiedName(com.oracle.truffle.dsl.processor.java.ElementUtils.getQualifiedName) CodeVariableElement(com.oracle.truffle.dsl.processor.java.model.CodeVariableElement) TruffleProcessorOptions(com.oracle.truffle.dsl.processor.TruffleProcessorOptions) ElementUtils.isVoid(com.oracle.truffle.dsl.processor.java.ElementUtils.isVoid) NodeData(com.oracle.truffle.dsl.processor.model.NodeData) CodeTypeElement(com.oracle.truffle.dsl.processor.java.model.CodeTypeElement) ABSTRACT(javax.lang.model.element.Modifier.ABSTRACT) Collection(java.util.Collection) DeclaredCodeTypeMirror(com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.DeclaredCodeTypeMirror) TypeKind(javax.lang.model.type.TypeKind) Objects(java.util.Objects) List(java.util.List) TemplateMethod(com.oracle.truffle.dsl.processor.model.TemplateMethod) Entry(java.util.Map.Entry) ElementUtils.isSubtypeBoxed(com.oracle.truffle.dsl.processor.java.ElementUtils.isSubtypeBoxed) Binary(com.oracle.truffle.dsl.processor.expression.DSLExpression.Binary) ArrayCodeTypeMirror(com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror) NodeParser(com.oracle.truffle.dsl.processor.parser.NodeParser) ElementUtils.isPrimitive(com.oracle.truffle.dsl.processor.java.ElementUtils.isPrimitive) SpecializationData(com.oracle.truffle.dsl.processor.model.SpecializationData) TypeSystemData(com.oracle.truffle.dsl.processor.model.TypeSystemData) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HashMap(java.util.HashMap) Function(java.util.function.Function) HashSet(java.util.HashSet) ElementUtils.isSubtype(com.oracle.truffle.dsl.processor.java.ElementUtils.isSubtype) ElementUtils.typeEquals(com.oracle.truffle.dsl.processor.java.ElementUtils.typeEquals) ElementUtils.getAnnotationValue(com.oracle.truffle.dsl.processor.java.ElementUtils.getAnnotationValue) ElementUtils(com.oracle.truffle.dsl.processor.java.ElementUtils) ElementUtils.executableEquals(com.oracle.truffle.dsl.processor.java.ElementUtils.executableEquals) CodeAnnotationMirror(com.oracle.truffle.dsl.processor.java.model.CodeAnnotationMirror) PRIVATE(javax.lang.model.element.Modifier.PRIVATE) Iterator(java.util.Iterator) ReentrantLock(java.util.concurrent.locks.ReentrantLock) Call(com.oracle.truffle.dsl.processor.expression.DSLExpression.Call) PUBLIC(javax.lang.model.element.Modifier.PUBLIC) ExecutableElement(javax.lang.model.element.ExecutableElement) GeneratedTypeMirror(com.oracle.truffle.dsl.processor.java.model.GeneratedTypeMirror) STATIC(javax.lang.model.element.Modifier.STATIC) TypeMirror(javax.lang.model.type.TypeMirror) ElementUtils.modifiers(com.oracle.truffle.dsl.processor.java.ElementUtils.modifiers) ElementUtils.firstLetterLowerCase(com.oracle.truffle.dsl.processor.java.ElementUtils.firstLetterLowerCase) Comparator(java.util.Comparator) Collections(java.util.Collections) CodeExecutableElement(com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement) ArrayList(java.util.ArrayList) CacheExpression(com.oracle.truffle.dsl.processor.model.CacheExpression) LinkedHashMap(java.util.LinkedHashMap) 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) ArrayList(java.util.ArrayList) List(java.util.List) LinkedHashSet(java.util.LinkedHashSet) HashSet(java.util.HashSet) AssumptionExpression(com.oracle.truffle.dsl.processor.model.AssumptionExpression) ReentrantLock(java.util.concurrent.locks.ReentrantLock) GuardExpression(com.oracle.truffle.dsl.processor.model.GuardExpression) GeneratedTypeMirror(com.oracle.truffle.dsl.processor.java.model.GeneratedTypeMirror) SpecializationData(com.oracle.truffle.dsl.processor.model.SpecializationData) SpecializationGroup(com.oracle.truffle.dsl.processor.parser.SpecializationGroup) NodeData(com.oracle.truffle.dsl.processor.model.NodeData) Parameter(com.oracle.truffle.dsl.processor.model.Parameter) ElementUtils.isObject(com.oracle.truffle.dsl.processor.java.ElementUtils.isObject) CodeTreeBuilder(com.oracle.truffle.dsl.processor.java.model.CodeTreeBuilder) TypeGuard(com.oracle.truffle.dsl.processor.parser.SpecializationGroup.TypeGuard)

Aggregations

ProcessorContext (com.oracle.truffle.dsl.processor.ProcessorContext)2 DSLExpression (com.oracle.truffle.dsl.processor.expression.DSLExpression)2 ElementUtils (com.oracle.truffle.dsl.processor.java.ElementUtils)2 ElementUtils.findAnnotationMirror (com.oracle.truffle.dsl.processor.java.ElementUtils.findAnnotationMirror)2 ElementUtils.firstLetterLowerCase (com.oracle.truffle.dsl.processor.java.ElementUtils.firstLetterLowerCase)2 ElementUtils.firstLetterUpperCase (com.oracle.truffle.dsl.processor.java.ElementUtils.firstLetterUpperCase)2 ElementUtils.getAnnotationValue (com.oracle.truffle.dsl.processor.java.ElementUtils.getAnnotationValue)2 ElementUtils.getQualifiedName (com.oracle.truffle.dsl.processor.java.ElementUtils.getQualifiedName)2 ElementUtils.getSimpleName (com.oracle.truffle.dsl.processor.java.ElementUtils.getSimpleName)2 ElementUtils.getTypeId (com.oracle.truffle.dsl.processor.java.ElementUtils.getTypeId)2 ElementUtils.isAssignable (com.oracle.truffle.dsl.processor.java.ElementUtils.isAssignable)2 ElementUtils.isSubtype (com.oracle.truffle.dsl.processor.java.ElementUtils.isSubtype)2 ElementUtils.modifiers (com.oracle.truffle.dsl.processor.java.ElementUtils.modifiers)2 ElementUtils.typeEquals (com.oracle.truffle.dsl.processor.java.ElementUtils.typeEquals)2 CodeAnnotationMirror (com.oracle.truffle.dsl.processor.java.model.CodeAnnotationMirror)2 CodeAnnotationValue (com.oracle.truffle.dsl.processor.java.model.CodeAnnotationValue)2 CodeExecutableElement (com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement)2 CodeNames (com.oracle.truffle.dsl.processor.java.model.CodeNames)2 CodeTypeElement (com.oracle.truffle.dsl.processor.java.model.CodeTypeElement)2 CodeVariableElement (com.oracle.truffle.dsl.processor.java.model.CodeVariableElement)2