Search in sources :

Example 1 with FlatNodeGenFactory

use of com.oracle.truffle.dsl.processor.generator.FlatNodeGenFactory in project graal by oracle.

the class ExportsGenerator method createCached.

CodeTypeElement createCached(ExportsLibrary libraryExports, Map<String, ExportMessageData> messages) {
    TypeMirror exportReceiverType = libraryExports.getReceiverType();
    final Modifier classVisibility = resolveSubclassVisibility(libraryExports);
    final boolean isFinalExports = classVisibility == Modifier.PRIVATE;
    final boolean isExtendsExports = isExtendsBaseExports(libraryExports);
    final Map<CacheKey, List<CacheExpression>> mergedLibraries = new LinkedHashMap<>();
    for (ExportMessageData message : messages.values()) {
        if (message.getSpecializedNode() != null) {
            groupMergedLibraries(message.getSpecializedNode().getSpecializations(), mergedLibraries);
        }
    }
    // caches initialized as part
    final ExportMessageData acceptsMessage = messages.get(ACCEPTS);
    Map<CacheKey, List<CacheExpression>> eagerCaches = initializeEagerCaches(messages);
    TypeMirror cachedBaseType = createBaseClassReference(libraryExports, "Cached");
    CodeTypeElement cacheClass = createClass(libraryExports, null, modifiers(PROTECTED, STATIC, FINAL), "Cached", cachedBaseType);
    ElementUtils.setVisibility(cacheClass.getModifiers(), classVisibility);
    ElementUtils.setFinal(cacheClass.getModifiers(), isFinalExports);
    CodeTree acceptsAssertions = createDynamicDispatchAssertions(libraryExports, messages);
    Set<NodeData> cachedSharedNodes = new LinkedHashSet<>();
    for (ExportMessageData export : messages.values()) {
        if (export.getSpecializedNode() != null) {
            cachedSharedNodes.add(export.getSpecializedNode());
        }
    }
    CodeExecutableElement constructor = cacheClass.add(GeneratorUtils.createConstructorUsingFields(modifiers(PROTECTED), cacheClass));
    CodeTreeBuilder builder = constructor.appendBuilder();
    if (isExtendsExports) {
        builder.startStatement().startSuperCall().string("receiver").end().end();
    }
    String receiverLocalName = "receiver";
    if (needsReceiver(libraryExports, messages, true)) {
        constructor.addParameter(new CodeVariableElement(context.getType(Object.class), receiverLocalName));
        boolean needsCast;
        if (hasConstructorCacheInitializer(messages)) {
            needsCast = true;
        } else if (!libraryExports.needsDynamicDispatch() && !libraryExports.isFinalReceiver()) {
            needsCast = !useSuperAccepts(libraryExports, messages);
        } else {
            needsCast = false;
        }
        if (libraryExports.isUseForAOT() && !mergedLibraries.isEmpty()) {
            builder.startIf().string("!(", receiverLocalName).string(" instanceof ").type(types.LibraryExport).string(")").end().startBlock();
        }
        if (needsCast && ElementUtils.needsCastTo(context.getType(Object.class), libraryExports.getReceiverType())) {
            String oldReceiverName = receiverLocalName;
            receiverLocalName = "castReceiver";
            builder.declaration(libraryExports.getReceiverType(), receiverLocalName, CodeTreeBuilder.createBuilder().maybeCast(context.getType(Object.class), libraryExports.getReceiverType(), oldReceiverName).build());
        }
        for (CacheKey key : mergedLibraries.keySet()) {
            CodeTree mergedLibraryIdentifier = writeExpression(key.cache, receiverLocalName, libraryExports.getReceiverType(), libraryExports.getReceiverType());
            String identifier = key.getCache().getMergedLibraryIdentifier();
            builder.startStatement();
            builder.string("this.", identifier, " = super.insert(");
            builder.staticReference(useLibraryConstant(key.libraryType)).startCall(".create").tree(mergedLibraryIdentifier).end();
            builder.string(")").end();
            CodeVariableElement var = cacheClass.add(new CodeVariableElement(modifiers(PRIVATE), key.libraryType, identifier));
            var.getAnnotationMirrors().add(new CodeAnnotationMirror(types.Node_Child));
        }
        if (libraryExports.isUseForAOT()) {
            builder.end();
        }
        if (acceptsMessage != null && acceptsMessage.getSpecializedNode() != null && acceptsMessage.isDeclared()) {
            SpecializationData firstSpecialization = null;
            for (SpecializationData s : acceptsMessage.getSpecializedNode().getSpecializations()) {
                if (!s.isSpecialized() || !s.isReachable()) {
                    continue;
                }
                firstSpecialization = s;
                break;
            }
            FlatNodeGenFactory factory = new FlatNodeGenFactory(context, GeneratorMode.EXPORTED_MESSAGE, acceptsMessage.getSpecializedNode(), cachedSharedNodes, libraryExports.getSharedExpressions(), constants);
            List<CacheExpression> caches = new ArrayList<>();
            for (CacheKey key : eagerCaches.keySet()) {
                caches.add(key.cache);
            }
            if (firstSpecialization == null) {
                throw new AssertionError();
            }
            builder.tree(factory.createInitializeCaches(firstSpecialization, caches, constructor, receiverLocalName));
        }
    }
    if (libraryExports.hasExportDelegation()) {
        cacheClass.getImplements().add(types.LibraryExport_DelegateExport);
        CodeExecutableElement getExportMessages = CodeExecutableElement.clone(ElementUtils.findExecutableElement(types.LibraryExport_DelegateExport, "getDelegateExportMessages"));
        getExportMessages.getModifiers().remove(Modifier.ABSTRACT);
        builder = getExportMessages.createBuilder();
        builder.startReturn().string(ENABLED_MESSAGES_NAME).end();
        cacheClass.add(getExportMessages);
        CodeExecutableElement readDelegate = CodeExecutableElement.clone(ElementUtils.findExecutableElement(types.LibraryExport_DelegateExport, "readDelegateExport"));
        readDelegate.getModifiers().remove(Modifier.ABSTRACT);
        readDelegate.renameArguments("receiver_");
        builder = readDelegate.createBuilder();
        builder.startReturn();
        builder.tree(createReceiverCast(libraryExports, messages, readDelegate.getParameters().get(0).asType(), libraryExports.getReceiverType(), CodeTreeBuilder.singleString("receiver_"), true));
        builder.string(".").string(libraryExports.getDelegationVariable().getSimpleName().toString());
        builder.end();
        cacheClass.add(readDelegate);
        // find merged library for the delegation
        CodeExecutableElement acceptsMethod = (CodeExecutableElement) messages.get(ACCEPTS).getMessageElement();
        VariableElement delegateLibraryParam = acceptsMethod.getParameters().get(1);
        String mergedLibraryId = null;
        outer: for (Entry<CacheKey, List<CacheExpression>> library : mergedLibraries.entrySet()) {
            for (CacheExpression cache : library.getValue()) {
                if (ElementUtils.variableEquals(cache.getParameter().getVariableElement(), delegateLibraryParam)) {
                    mergedLibraryId = library.getKey().getCache().getMergedLibraryIdentifier();
                    break outer;
                }
            }
        }
        if (mergedLibraryId == null) {
            throw new AssertionError("Could not find merged library for export delegation.");
        }
        CodeExecutableElement getDelegateLibrary = CodeExecutableElement.clone(ElementUtils.findExecutableElement(types.LibraryExport_DelegateExport, "getDelegateExportLibrary"));
        getDelegateLibrary.getModifiers().remove(Modifier.ABSTRACT);
        builder = getDelegateLibrary.createBuilder();
        builder.startReturn().string("this.", mergedLibraryId).end();
        cacheClass.add(getDelegateLibrary);
    }
    CodeTree defaultAccepts = createDefaultAccepts(cacheClass, constructor, libraryExports, messages, exportReceiverType, receiverLocalName, "receiver", true);
    CodeExecutableElement accepts = CodeExecutableElement.clone(ElementUtils.findExecutableElement(types.Library, ACCEPTS));
    GeneratorUtils.addOverride(accepts);
    accepts.getModifiers().remove(Modifier.ABSTRACT);
    accepts.renameArguments("receiver");
    builder = accepts.createBuilder();
    if (acceptsAssertions != null) {
        builder.tree(acceptsAssertions);
    }
    if (mergedLibraries.isEmpty()) {
        builder.startReturn();
        if (acceptsMessage == null || acceptsMessage.isGenerated()) {
            builder.tree(defaultAccepts);
            if (useSuperAccepts(libraryExports, messages)) {
                // we don't need an accepts method because
                // we just call super.accepts
                accepts = null;
            }
        } else {
            builder.tree(defaultAccepts).string(" && accepts_(receiver)");
        }
        builder.end();
    } else {
        builder.startIf().string("!(").tree(defaultAccepts).string(")").end();
        builder.startBlock();
        builder.returnFalse();
        builder.end();
        for (CacheKey key : mergedLibraries.keySet()) {
            CodeTree mergedLibraryInitializer = writeExpression(key.cache, "receiver", context.getType(Object.class), libraryExports.getReceiverType());
            String identifier = key.getCache().getMergedLibraryIdentifier();
            builder.startElseIf();
            if (libraryExports.isUseForAOT()) {
                builder.string("this.", identifier, " != null && ");
            }
            builder.string("!this.", identifier);
            builder.startCall(".accepts").tree(mergedLibraryInitializer).end();
            builder.end().startBlock();
            builder.returnFalse();
            builder.end();
        }
        builder.startElseBlock();
        if (acceptsMessage != null && !acceptsMessage.isGenerated()) {
            builder.startReturn();
            builder.string("accepts_(receiver)");
            builder.end();
        } else {
            builder.returnTrue();
        }
        builder.end();
    }
    cacheClass.addOptional(createCastMethod(libraryExports, messages, exportReceiverType, true));
    cacheClass.addOptional(accepts);
    if (!libraryExports.needsRewrites() && useSingleton(libraryExports, messages, true)) {
        CodeExecutableElement isAdoptable = cacheClass.add(CodeExecutableElement.clone(ElementUtils.findExecutableElement(types.Node, "isAdoptable")));
        builder = isAdoptable.createBuilder();
        if (libraryExports.needsDynamicDispatch()) {
            builder.startReturn();
            builder.startCall("dynamicDispatch_", "isAdoptable").end();
            builder.end();
        } else {
            builder.returnFalse();
        }
    }
    if (libraryExports.isAllowTransition()) {
        TypeMirror libraryType = libraryExports.getLibrary().getTemplateType().asType();
        CodeExecutableElement fallback = cacheClass.add(new CodeExecutableElement(modifiers(PRIVATE), libraryType, "getFallback_"));
        fallback.addParameter(new CodeVariableElement(libraryExports.getLibrary().getSignatureReceiverType(), "receiver"));
        CodeVariableElement fallbackVar = cacheClass.add(new CodeVariableElement(modifiers(PRIVATE), libraryType, "fallback_"));
        fallbackVar.addAnnotationMirror(new CodeAnnotationMirror(types.Node_Child));
        builder = fallback.createBuilder();
        builder.declaration(libraryType, "localFallback", "this.fallback_");
        builder.startIf().string("localFallback == null").end().startBlock();
        builder.tree(GeneratorUtils.createTransferToInterpreterAndInvalidate());
        builder.startStatement();
        CodeTree transitionLimit = DSLExpressionGenerator.write(libraryExports.getTransitionLimit(), null, Collections.emptyMap());
        builder.string("this.fallback_ = localFallback = insert(").staticReference(useLibraryConstant(libraryType)).startCall(".createDispatched").tree(transitionLimit).end().string(")");
        // statement
        builder.end();
        // block
        builder.end();
        builder.startReturn().string("localFallback").end();
    }
    Map<NodeData, CodeTypeElement> sharedNodes = new HashMap<>();
    for (ExportMessageData export : messages.values()) {
        if (export.isGenerated()) {
            continue;
        }
        LibraryMessage message = export.getResolvedMessage();
        TypeMirror cachedExportReceiverType = export.getExportsLibrary().getReceiverType();
        // cached execute
        NodeData cachedSpecializedNode = export.getSpecializedNode();
        CodeExecutableElement cachedExecute = null;
        if (cachedSpecializedNode == null) {
            if (!export.isMethod()) {
                throw new AssertionError("Missing method export. Missed validation for " + export.getResolvedMessage().getSimpleName());
            }
            boolean isAccepts = message.getMessageElement().getSimpleName().toString().equals(ACCEPTS);
            TypeMirror modelReceiverType;
            if (isAccepts) {
                modelReceiverType = context.getType(Object.class);
            } else {
                modelReceiverType = message.getLibrary().getSignatureReceiverType();
            }
            ExecutableElement exportMethod = (ExecutableElement) export.getMessageElement();
            CodeTree cachedReceiverAccess = createReceiverCast(libraryExports, messages, modelReceiverType, cachedExportReceiverType, CodeTreeBuilder.singleString("receiver"), true);
            cachedReceiverAccess = CodeTreeBuilder.createBuilder().startParantheses().tree(cachedReceiverAccess).end().build();
            cachedExecute = cacheClass.add(createDirectCall(cachedReceiverAccess, message, exportMethod));
        } else {
            CodeTypeElement dummyNodeClass = sharedNodes.get(cachedSpecializedNode);
            boolean shared = true;
            if (dummyNodeClass == null) {
                FlatNodeGenFactory factory = new FlatNodeGenFactory(context, GeneratorMode.EXPORTED_MESSAGE, cachedSpecializedNode, cachedSharedNodes, libraryExports.getSharedExpressions(), constants);
                dummyNodeClass = createClass(libraryExports, null, modifiers(), "Dummy", types.Node);
                factory.create(dummyNodeClass);
                sharedNodes.put(cachedSpecializedNode, dummyNodeClass);
                shared = false;
            }
            for (Element element : dummyNodeClass.getEnclosedElements()) {
                String simpleName = element.getSimpleName().toString();
                if (element.getKind() == ElementKind.METHOD) {
                    if (simpleName.endsWith("AndSpecialize")) {
                    // nothing to do for specialize method
                    } else if (simpleName.startsWith(ExportsParser.EXECUTE_PREFIX) && simpleName.endsWith(ExportsParser.EXECUTE_SUFFIX)) {
                        CodeExecutableElement executable = (CodeExecutableElement) element;
                        executable.setVarArgs(message.getExecutable().isVarArgs());
                        cachedExecute = CodeExecutableElement.clone(executable);
                        cachedExecute.setSimpleName(CodeNames.of(message.getName()));
                        injectReceiverType(cachedExecute, libraryExports, messages, cachedExportReceiverType, true);
                        cacheClass.getEnclosedElements().add(cachedExecute);
                        continue;
                    }
                } else if (element.getKind() == ElementKind.CONSTRUCTOR) {
                    // no constructores needed
                    continue;
                }
                if (!shared) {
                    if (simpleName.equals("prepareForAOT")) {
                        TypeMirror aotProviderType = new GeneratedTypeMirror(ElementUtils.getPackageName(types.GenerateAOT_Provider), "GenerateAOT.Provider");
                        cacheClass.getImplements().add(aotProviderType);
                    }
                    // only execute method needed for shared
                    cacheClass.getEnclosedElements().add(element);
                }
            }
        }
        if (cachedExecute == null) {
            throw new AssertionError("execute not found");
        }
        if (message.getName().equals(ACCEPTS)) {
            if (export.getExportsLibrary().isFinalReceiver() && (cachedSpecializedNode == null || !cachedSpecializedNode.needsRewrites(context)) && eagerCaches.isEmpty()) {
                cachedExecute.getModifiers().add(Modifier.STATIC);
            }
            cachedExecute.setSimpleName(CodeNames.of(ACCEPTS_METHOD_NAME));
            ElementUtils.setVisibility(cachedExecute.getModifiers(), Modifier.PRIVATE);
        } else {
            GeneratorUtils.addOverride(cachedExecute);
            if (!isFinalExports) {
                // if this message might be extended we need to fully match the exception
                // signature
                GeneratorUtils.addThrownExceptions(cachedExecute, export.getResolvedMessage().getExecutable().getThrownTypes());
            }
            if (libraryExports.needsRewrites()) {
                injectCachedAssertions(export.getExportsLibrary().getLibrary(), cachedExecute);
            }
            CodeTree originalBody = cachedExecute.getBodyTree();
            CodeTreeBuilder b = cachedExecute.createBuilder();
            if (libraryExports.isAllowTransition()) {
                b.startAssert();
                String name = cachedExecute.getParameters().get(0).getSimpleName().toString();
                b.tree(createDefaultAccepts(null, null, libraryExports, messages, libraryExports.getReceiverType(), null, name, true));
                b.string(" : ").doubleQuote(INVALID_LIBRARY_USAGE_MESSAGE);
                b.end();
                b.startIf().startCall("this.accepts").string(name).end().end().startBlock();
                b.tree(originalBody);
                b.end();
                b.startElseBlock();
                b.startReturn();
                b.startCall("getFallback_").string(name).end().string(".");
                b.startCall(cachedExecute.getSimpleName().toString());
                for (VariableElement param : cachedExecute.getParameters()) {
                    b.string(param.getSimpleName().toString());
                }
                // call
                b.end();
                // return
                b.end();
                // block
                b.end();
            } else {
                CodeTree customAcceptsAssertion;
                if (mergedLibraries.isEmpty()) {
                    // use normal accepts call
                    customAcceptsAssertion = null;
                } else {
                    // with merged libraries we need to use the default accepts
                    // for the assertion as merged libraries might require transitions
                    String name = b.findMethod().getParameters().get(0).getSimpleName().toString();
                    customAcceptsAssertion = createDefaultAccepts(null, null, libraryExports, messages, exportReceiverType, null, name, true);
                }
                addAcceptsAssertion(b, customAcceptsAssertion);
                b.tree(originalBody);
            }
        }
    }
    return cacheClass;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) CodeExecutableElement(com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) CodeExecutableElement(com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) 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) CacheExpression(com.oracle.truffle.dsl.processor.model.CacheExpression) LinkedHashMap(java.util.LinkedHashMap) Entry(java.util.Map.Entry) CodeTypeMirror(com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror) GeneratedTypeMirror(com.oracle.truffle.dsl.processor.java.model.GeneratedTypeMirror) TypeMirror(javax.lang.model.type.TypeMirror) CodeTypeElement(com.oracle.truffle.dsl.processor.java.model.CodeTypeElement) CodeTree(com.oracle.truffle.dsl.processor.java.model.CodeTree) CodeVariableElement(com.oracle.truffle.dsl.processor.java.model.CodeVariableElement) List(java.util.List) ArrayList(java.util.ArrayList) Modifier(javax.lang.model.element.Modifier) CodeAnnotationMirror(com.oracle.truffle.dsl.processor.java.model.CodeAnnotationMirror) GeneratedTypeMirror(com.oracle.truffle.dsl.processor.java.model.GeneratedTypeMirror) SpecializationData(com.oracle.truffle.dsl.processor.model.SpecializationData) NodeData(com.oracle.truffle.dsl.processor.model.NodeData) FlatNodeGenFactory(com.oracle.truffle.dsl.processor.generator.FlatNodeGenFactory) CodeTreeBuilder(com.oracle.truffle.dsl.processor.java.model.CodeTreeBuilder)

Example 2 with FlatNodeGenFactory

use of com.oracle.truffle.dsl.processor.generator.FlatNodeGenFactory in project graal by oracle.

the class ExportsGenerator method createUncached.

CodeTypeElement createUncached(ExportsLibrary libraryExports, Map<String, ExportMessageData> messages) {
    final TypeMirror exportReceiverType = libraryExports.getReceiverType();
    final Modifier classVisibility = resolveSubclassVisibility(libraryExports);
    final boolean isFinalExports = classVisibility == Modifier.PRIVATE;
    final boolean isExtendsExports = isExtendsBaseExports(libraryExports);
    TypeMirror uncachedBaseType = createBaseClassReference(libraryExports, "Uncached");
    CodeTypeElement uncachedClass = createClass(libraryExports, null, modifiers(PRIVATE, STATIC, FINAL), "Uncached", uncachedBaseType);
    ElementUtils.setVisibility(uncachedClass.getModifiers(), classVisibility);
    ElementUtils.setFinal(uncachedClass.getModifiers(), isFinalExports);
    CodeTreeBuilder builder;
    CodeExecutableElement constructor = uncachedClass.add(GeneratorUtils.createConstructorUsingFields(modifiers(PROTECTED), uncachedClass));
    if (needsReceiver(libraryExports, messages, false)) {
        constructor.addParameter(new CodeVariableElement(context.getType(Object.class), "receiver"));
        if (isExtendsExports) {
            builder = constructor.appendBuilder();
            builder.startStatement().startSuperCall().string("receiver").end().end();
        }
    }
    if (libraryExports.hasExportDelegation()) {
        uncachedClass.getImplements().add(types.LibraryExport_DelegateExport);
        CodeExecutableElement getExportMessages = CodeExecutableElement.clone(ElementUtils.findExecutableElement(types.LibraryExport_DelegateExport, "getDelegateExportMessages"));
        getExportMessages.getModifiers().remove(Modifier.ABSTRACT);
        builder = getExportMessages.createBuilder();
        builder.startReturn().string(ENABLED_MESSAGES_NAME).end();
        uncachedClass.add(getExportMessages);
        CodeExecutableElement readDelegate = CodeExecutableElement.clone(ElementUtils.findExecutableElement(types.LibraryExport_DelegateExport, "readDelegateExport"));
        readDelegate.getModifiers().remove(Modifier.ABSTRACT);
        readDelegate.renameArguments("receiver_");
        builder = readDelegate.createBuilder();
        builder.startReturn();
        builder.string("(");
        builder.tree(createReceiverCast(libraryExports, messages, readDelegate.getParameters().get(0).asType(), libraryExports.getReceiverType(), CodeTreeBuilder.singleString("receiver_"), false));
        builder.string(")");
        builder.string(".").string(libraryExports.getDelegationVariable().getSimpleName().toString());
        builder.end();
        uncachedClass.add(readDelegate);
        // find merged library for the delegation
        CodeExecutableElement getDelegateLibrary = CodeExecutableElement.clone(ElementUtils.findExecutableElement(types.LibraryExport_DelegateExport, "getDelegateExportLibrary"));
        getDelegateLibrary.renameArguments("delegate_");
        getDelegateLibrary.getModifiers().remove(Modifier.ABSTRACT);
        builder = getDelegateLibrary.createBuilder();
        builder.startReturn();
        builder.staticReference(useLibraryConstant(libraryExports.getLibrary().getTemplateType().asType()));
        builder.string(".getUncached(delegate_)");
        builder.end();
        uncachedClass.add(getDelegateLibrary);
    }
    ExportMessageData accepts = messages.get(ACCEPTS);
    CodeTree acceptsAssertions = createDynamicDispatchAssertions(libraryExports, messages);
    CodeTree defaultAccepts = createDefaultAccepts(uncachedClass, constructor, libraryExports, messages, exportReceiverType, "receiver", "receiver", false);
    CodeExecutableElement acceptUncached = CodeExecutableElement.clone(ElementUtils.findExecutableElement(types.Library, ACCEPTS));
    GeneratorUtils.addOverride(acceptUncached);
    acceptUncached.getModifiers().remove(Modifier.ABSTRACT);
    acceptUncached.renameArguments("receiver");
    builder = acceptUncached.createBuilder();
    GeneratorUtils.addBoundaryOrTransferToInterpreter(acceptUncached, builder);
    if (acceptsAssertions != null) {
        builder.tree(acceptsAssertions);
    }
    if (accepts == null || accepts.isGenerated()) {
        builder.startReturn().tree(defaultAccepts).end();
    } else {
        builder.startReturn().tree(defaultAccepts).string(" && accepts_(receiver)").end();
    }
    builder.end();
    uncachedClass.add(acceptUncached);
    uncachedClass.addOptional(createCastMethod(libraryExports, messages, exportReceiverType, false));
    Set<NodeData> uncachedSharedNodes = new LinkedHashSet<>();
    for (ExportMessageData export : messages.values()) {
        if (export.getSpecializedNode() != null) {
            uncachedSharedNodes.add(export.getSpecializedNode());
        }
    }
    if (!isExtendsExports) {
        CodeExecutableElement isAdoptable = uncachedClass.add(CodeExecutableElement.clone(ElementUtils.findExecutableElement(types.Node, "isAdoptable")));
        ElementUtils.setFinal(isAdoptable.getModifiers(), !isFinalExports);
        isAdoptable.createBuilder().returnFalse();
    }
    if (!isExtendsExports) {
        CodeExecutableElement getCost = uncachedClass.add(CodeExecutableElement.clone(ElementUtils.findExecutableElement(types.Node, "getCost")));
        ElementUtils.setFinal(getCost.getModifiers(), !isFinalExports);
        getCost.createBuilder().startReturn().staticReference(ElementUtils.findVariableElement(types.NodeCost, "MEGAMORPHIC")).end();
    }
    boolean firstNode = true;
    for (ExportMessageData export : messages.values()) {
        if (export.isGenerated()) {
            continue;
        }
        LibraryMessage message = export.getResolvedMessage();
        // uncached execute
        TypeMirror uncachedReceiverType = export.getReceiverType();
        TypeMirror messageReceiverType = message.getExecutable().getParameters().get(0).asType();
        CodeTree uncachedReceiverExport = CodeTreeBuilder.createBuilder().maybeCast(messageReceiverType, uncachedReceiverType, "receiver").build();
        CodeExecutableElement uncachedExecute;
        NodeData uncachedSpecializedNode = export.getSpecializedNode();
        if (uncachedSpecializedNode == null) {
            if (!export.isMethod()) {
                throw new AssertionError("Missing method export. Missed validation for " + export.getResolvedMessage().getSimpleName());
            }
            ExecutableElement exportMethod = (ExecutableElement) export.getMessageElement();
            CodeExecutableElement directCall = createDirectCall(uncachedReceiverExport, message, exportMethod);
            uncachedExecute = uncachedClass.add(directCall);
            if (message.getName().equals(ACCEPTS)) {
                directCall.getModifiers().add(Modifier.STATIC);
            }
        } else {
            FlatNodeGenFactory factory = new FlatNodeGenFactory(context, GeneratorMode.EXPORTED_MESSAGE, uncachedSpecializedNode, uncachedSharedNodes, Collections.emptyMap(), constants);
            CodeExecutableElement generatedUncached = factory.createUncached();
            if (firstNode) {
                uncachedClass.getEnclosedElements().addAll(factory.createUncachedFields());
                firstNode = false;
            }
            generatedUncached.getModifiers().remove(STATIC);
            ElementUtils.setVisibility(generatedUncached.getModifiers(), Modifier.PUBLIC);
            generatedUncached.setSimpleName(CodeNames.of(message.getName()));
            generatedUncached.setVarArgs(message.getExecutable().isVarArgs());
            injectReceiverType(generatedUncached, libraryExports, messages, uncachedReceiverType, false);
            uncachedExecute = uncachedClass.add(generatedUncached);
        }
        if (message.getName().equals(ACCEPTS)) {
            uncachedExecute.getModifiers().add(Modifier.STATIC);
            uncachedExecute.setSimpleName(CodeNames.of(ACCEPTS + "_"));
            ElementUtils.setVisibility(uncachedExecute.getModifiers(), Modifier.PRIVATE);
        } else {
            // prepend accepts assertion
            CodeTree originalBody = uncachedExecute.getBodyTree();
            CodeTreeBuilder b = uncachedExecute.createBuilder();
            b.lineComment("declared: " + export.isDeclared());
            GeneratorUtils.addBoundaryOrTransferToInterpreter(uncachedExecute, b);
            if (!isFinalExports) {
                // if this message might be extended we need to fully match the exception
                // signature
                GeneratorUtils.addThrownExceptions(uncachedExecute, export.getResolvedMessage().getExecutable().getThrownTypes());
            }
            GeneratorUtils.addOverride(uncachedExecute);
            addAcceptsAssertion(b, null);
            b.tree(originalBody);
        }
    }
    return uncachedClass;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) CodeExecutableElement(com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement) CodeExecutableElement(com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) NodeData(com.oracle.truffle.dsl.processor.model.NodeData) FlatNodeGenFactory(com.oracle.truffle.dsl.processor.generator.FlatNodeGenFactory) CodeTypeMirror(com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror) GeneratedTypeMirror(com.oracle.truffle.dsl.processor.java.model.GeneratedTypeMirror) TypeMirror(javax.lang.model.type.TypeMirror) CodeTypeElement(com.oracle.truffle.dsl.processor.java.model.CodeTypeElement) CodeTree(com.oracle.truffle.dsl.processor.java.model.CodeTree) CodeVariableElement(com.oracle.truffle.dsl.processor.java.model.CodeVariableElement) Modifier(javax.lang.model.element.Modifier) CodeTreeBuilder(com.oracle.truffle.dsl.processor.java.model.CodeTreeBuilder)

Aggregations

FlatNodeGenFactory (com.oracle.truffle.dsl.processor.generator.FlatNodeGenFactory)2 CodeExecutableElement (com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement)2 CodeTree (com.oracle.truffle.dsl.processor.java.model.CodeTree)2 CodeTreeBuilder (com.oracle.truffle.dsl.processor.java.model.CodeTreeBuilder)2 CodeTypeElement (com.oracle.truffle.dsl.processor.java.model.CodeTypeElement)2 CodeTypeMirror (com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror)2 CodeVariableElement (com.oracle.truffle.dsl.processor.java.model.CodeVariableElement)2 GeneratedTypeMirror (com.oracle.truffle.dsl.processor.java.model.GeneratedTypeMirror)2 NodeData (com.oracle.truffle.dsl.processor.model.NodeData)2 LinkedHashSet (java.util.LinkedHashSet)2 ExecutableElement (javax.lang.model.element.ExecutableElement)2 Modifier (javax.lang.model.element.Modifier)2 TypeMirror (javax.lang.model.type.TypeMirror)2 CodeAnnotationMirror (com.oracle.truffle.dsl.processor.java.model.CodeAnnotationMirror)1 CacheExpression (com.oracle.truffle.dsl.processor.model.CacheExpression)1 SpecializationData (com.oracle.truffle.dsl.processor.model.SpecializationData)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 LinkedHashMap (java.util.LinkedHashMap)1 List (java.util.List)1