Search in sources :

Example 1 with Clazz

use of org.robovm.compiler.clazz.Clazz in project robovm by robovm.

the class AppCompilerTest method testMultilineFile.

@Test
public void testMultilineFile() throws Exception {
    final Path impl1 = new MockPath("META-INF/services/java.lang.Number", "# first register Integer\n" + "java.lang.Integer\n" + "# then add Long\n" + "java.lang.Long\n" + "\n\n\n\n");
    Clazzes clazzes = createClazzes(impl1);
    Clazz interfaceClazz = clazzes.load("java/lang/Number");
    Set<Clazz> compiled = new HashSet<>();
    Set<Clazz> queue = new LinkedHashSet<>();
    AppCompiler.addMetaInfImplementations(clazzes, interfaceClazz, compiled, queue);
    assertEquals("Two items added to queue: " + queue, 2, queue.size());
    assertTrue("Integer in queue" + queue, queue.contains(clazzes.load("java/lang/Integer")));
    assertTrue("Long in queue" + queue, queue.contains(clazzes.load("java/lang/Long")));
}
Also used : Path(org.robovm.compiler.clazz.Path) LinkedHashSet(java.util.LinkedHashSet) Clazz(org.robovm.compiler.clazz.Clazz) Clazzes(org.robovm.compiler.clazz.Clazzes) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) Test(org.junit.Test)

Example 2 with Clazz

use of org.robovm.compiler.clazz.Clazz in project robovm by robovm.

the class AppCompilerTest method allStreamsAreClosedInCaseOfFailure.

@Test
public void allStreamsAreClosedInCaseOfFailure() throws Exception {
    final MockPath impl1 = new MockPath("META-INF/services/java.lang.Number", "java.lang.Integer");
    impl1.toThrow = new IOException();
    final MockPath impl2 = new MockPath("META-INF/services/java.lang.Number", "nobody.knows.such.Class");
    Clazzes clazzes = createClazzes(impl1, impl2);
    Clazz interfaceClazz = clazzes.load("java/lang/Number");
    Set<Clazz> compiled = new HashSet<>();
    Set<Clazz> queue = new LinkedHashSet<>();
    try {
        AppCompiler.addMetaInfImplementations(clazzes, interfaceClazz, compiled, queue);
        fail("Should throw an exception");
    } catch (IOException ex) {
        assertSame("Our exception is thrown", impl1.toThrow, ex);
    }
    assertTrue("First stream is closed", impl1.closed);
    assertTrue("Second stream is closed", impl2.closed);
}
Also used : LinkedHashSet(java.util.LinkedHashSet) Clazz(org.robovm.compiler.clazz.Clazz) IOException(java.io.IOException) Clazzes(org.robovm.compiler.clazz.Clazzes) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) Test(org.junit.Test)

Example 3 with Clazz

use of org.robovm.compiler.clazz.Clazz in project robovm by robovm.

the class AppCompilerTest method testMetainfServiceImplIsAdded.

@Test
public void testMetainfServiceImplIsAdded() throws Exception {
    final Path impl1 = new MockPath("META-INF/services/java.lang.Number", "java.lang.Integer");
    Clazzes clazzes = createClazzes(impl1);
    Clazz interfaceClazz = clazzes.load("java/lang/Number");
    Set<Clazz> compiled = new HashSet<>();
    Set<Clazz> queue = new LinkedHashSet<>();
    AppCompiler.addMetaInfImplementations(clazzes, interfaceClazz, compiled, queue);
    assertEquals("One item added to queue: " + queue, 1, queue.size());
    assertTrue("Integer in queue" + queue, queue.contains(clazzes.load("java/lang/Integer")));
}
Also used : Path(org.robovm.compiler.clazz.Path) LinkedHashSet(java.util.LinkedHashSet) Clazz(org.robovm.compiler.clazz.Clazz) Clazzes(org.robovm.compiler.clazz.Clazzes) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) Test(org.junit.Test)

Example 4 with Clazz

use of org.robovm.compiler.clazz.Clazz in project robovm by robovm.

the class Linker method link.

public void link(Set<Clazz> classes) throws IOException {
    for (CompilerPlugin plugin : config.getCompilerPlugins()) {
        plugin.beforeLinker(config, this, classes);
    }
    Arch arch = config.getArch();
    OS os = config.getOs();
    Set<Clazz> linkClasses = new TreeSet<Clazz>(classes);
    config.getLogger().info("Linking %d classes (%s %s %s)", linkClasses.size(), os, arch, config.isDebug() ? "debug" : "release");
    ModuleBuilder mb = new ModuleBuilder();
    mb.addInclude(getClass().getClassLoader().getResource(String.format("header-%s-%s.ll", os.getFamily(), arch)));
    mb.addInclude(getClass().getClassLoader().getResource("header.ll"));
    mb.addGlobal(new Global("_bcRuntimeData", runtimeDataToBytes()));
    ArrayConstantBuilder staticLibs = new ArrayConstantBuilder(I8_PTR);
    for (Config.Lib lib : config.getLibs()) {
        String p = lib.getValue();
        if (p.endsWith(".a")) {
            p = new File(p).getName();
            String libName = p.substring(0, p.length() - 2);
            if (libName.startsWith("lib")) {
                libName = libName.substring(3);
            }
            staticLibs.add(mb.getString(libName));
        }
    }
    staticLibs.add(new NullConstant(Type.I8_PTR));
    mb.addGlobal(new Global("_bcStaticLibs", new ConstantGetelementptr(mb.newGlobal(staticLibs.build()).ref(), 0, 0)));
    HashTableGenerator<String, Constant> bcpHashGen = new HashTableGenerator<String, Constant>(new ModifiedUtf8HashFunction());
    HashTableGenerator<String, Constant> cpHashGen = new HashTableGenerator<String, Constant>(new ModifiedUtf8HashFunction());
    int classCount = 0;
    Map<ClazzInfo, TypeInfo> typeInfos = new HashMap<ClazzInfo, TypeInfo>();
    for (Clazz clazz : linkClasses) {
        TypeInfo typeInfo = new TypeInfo();
        typeInfo.clazz = clazz;
        typeInfo.id = classCount++;
        typeInfos.put(clazz.getClazzInfo(), typeInfo);
        StructureConstant infoErrorStruct = createClassInfoErrorStruct(mb, clazz.getClazzInfo());
        Global info = null;
        if (infoErrorStruct == null) {
            info = new Global(Symbols.infoStructSymbol(clazz.getInternalName()), external, I8_PTR, false);
        } else {
            typeInfo.error = true;
            info = new Global(Symbols.infoStructSymbol(clazz.getInternalName()), infoErrorStruct);
        }
        mb.addGlobal(info);
        if (clazz.isInBootClasspath()) {
            bcpHashGen.put(clazz.getInternalName(), new ConstantBitcast(info.ref(), I8_PTR));
        } else {
            cpHashGen.put(clazz.getInternalName(), new ConstantBitcast(info.ref(), I8_PTR));
        }
    }
    mb.addGlobal(new Global("_bcBootClassesHash", new ConstantGetelementptr(mb.newGlobal(bcpHashGen.generate(), true).ref(), 0, 0)));
    mb.addGlobal(new Global("_bcClassesHash", new ConstantGetelementptr(mb.newGlobal(cpHashGen.generate(), true).ref(), 0, 0)));
    ArrayConstantBuilder bootClasspathValues = new ArrayConstantBuilder(I8_PTR);
    ArrayConstantBuilder classpathValues = new ArrayConstantBuilder(I8_PTR);
    List<Path> allPaths = new ArrayList<Path>();
    allPaths.addAll(config.getClazzes().getPaths());
    allPaths.addAll(config.getResourcesPaths());
    for (Path path : allPaths) {
        String entryName = null;
        if (config.isSkipInstall() && config.getTarget().canLaunchInPlace()) {
            entryName = path.getFile().getAbsolutePath();
        } else {
            entryName = config.getTarget().getInstallRelativeArchivePath(path);
        }
        if (path.isInBootClasspath()) {
            bootClasspathValues.add(mb.getString(entryName));
        } else {
            classpathValues.add(mb.getString(entryName));
        }
    }
    bootClasspathValues.add(new NullConstant(Type.I8_PTR));
    classpathValues.add(new NullConstant(Type.I8_PTR));
    mb.addGlobal(new Global("_bcBootclasspath", new ConstantGetelementptr(mb.newGlobal(bootClasspathValues.build()).ref(), 0, 0)));
    mb.addGlobal(new Global("_bcClasspath", new ConstantGetelementptr(mb.newGlobal(classpathValues.build()).ref(), 0, 0)));
    if (config.getMainClass() != null) {
        mb.addGlobal(new Global("_bcMainClass", mb.getString(config.getMainClass())));
    }
    ModuleBuilder[] mbs = new ModuleBuilder[config.getThreads() + 1];
    FunctionRef[] stubRefs = new FunctionRef[mbs.length];
    ArrayConstantBuilder stubRefsArray = new ArrayConstantBuilder(I8_PTR);
    mbs[0] = mb;
    for (int i = 1; i < mbs.length; i++) {
        mbs[i] = new ModuleBuilder();
        mbs[i].addInclude(getClass().getClassLoader().getResource(String.format("header-%s-%s.ll", os.getFamily(), arch)));
        mbs[i].addInclude(getClass().getClassLoader().getResource("header.ll"));
        Function fn = new FunctionBuilder("_stripped_method" + i, new FunctionType(VOID, ENV_PTR)).linkage(external).build();
        call(fn, BC_THROW_NO_SUCH_METHOD_ERROR, fn.getParameterRef(0), mbs[i].getString("Method has been stripped out of the executable"));
        fn.add(new Unreachable());
        mbs[i].addFunction(fn);
        mb.addFunctionDeclaration(new FunctionDeclaration(fn.ref()));
        stubRefs[i] = fn.ref();
        stubRefsArray.add(new ConstantBitcast(fn.ref(), I8_PTR));
    }
    stubRefsArray.add(new NullConstant(I8_PTR));
    mb.addGlobal(new Global("_bcStrippedMethodStubs", stubRefsArray.build()));
    Random rnd = new Random();
    buildTypeInfos(typeInfos);
    Set<String> checkcasts = new HashSet<>();
    Set<String> instanceofs = new HashSet<>();
    Set<String> invokes = new HashSet<>();
    for (Clazz clazz : linkClasses) {
        ClazzInfo ci = clazz.getClazzInfo();
        checkcasts.addAll(ci.getCheckcasts());
        instanceofs.addAll(ci.getInstanceofs());
        invokes.addAll(ci.getInvokes());
    }
    Set<String> reachableMethods = new HashSet<>();
    for (Triple<String, String, String> node : config.getDependencyGraph().findReachableMethods()) {
        reachableMethods.add(node.getLeft() + "." + node.getMiddle() + node.getRight());
    }
    int totalMethodCount = 0;
    int reachableMethodCount = 0;
    for (Clazz clazz : linkClasses) {
        int mbIdx = rnd.nextInt(mbs.length - 1) + 1;
        ClazzInfo ci = clazz.getClazzInfo();
        // symbols errors.
        for (MethodInfo mi : ci.getMethods()) {
            if (!mi.isAbstract()) {
                totalMethodCount++;
                if (!reachableMethods.contains(clazz.getInternalName() + "." + mi.getName() + mi.getDesc())) {
                    createStrippedMethodStub(stubRefs[mbIdx], mbs[mbIdx], clazz, mi);
                } else {
                    reachableMethodCount++;
                }
            }
        }
        TypeInfo typeInfo = typeInfos.get(ci);
        if (typeInfo.error) {
            // Add an empty TypeInfo
            mb.addGlobal(new Global(Symbols.typeInfoSymbol(clazz.getInternalName()), new StructureConstantBuilder().add(new IntegerConstant(typeInfo.id)).add(new IntegerConstant(0)).add(new IntegerConstant(-1)).add(new IntegerConstant(0)).add(new IntegerConstant(0)).build()));
        } else {
            int[] classIds = new int[typeInfo.classTypes.length];
            for (int i = 0; i < typeInfo.classTypes.length; i++) {
                classIds[i] = typeInfo.classTypes[i].id;
            }
            int[] interfaceIds = new int[typeInfo.interfaceTypes.length];
            for (int i = 0; i < typeInfo.interfaceTypes.length; i++) {
                interfaceIds[i] = typeInfo.interfaceTypes[i].id;
            }
            mb.addGlobal(new Global(Symbols.typeInfoSymbol(clazz.getInternalName()), new StructureConstantBuilder().add(new IntegerConstant(typeInfo.id)).add(new IntegerConstant((typeInfo.classTypes.length - 1) * 4 + 5 * 4)).add(new IntegerConstant(-1)).add(new IntegerConstant(typeInfo.classTypes.length)).add(new IntegerConstant(typeInfo.interfaceTypes.length)).add(new ArrayConstantBuilder(I32).add(classIds).build()).add(new ArrayConstantBuilder(I32).add(interfaceIds).build()).build()));
            if (!config.isDebug() && !ci.isInterface() && !ci.isFinal() && typeInfo.children.isEmpty()) {
                // which doesn't do any lookup.
                for (MethodInfo mi : ci.getMethods()) {
                    String name = mi.getName();
                    if (!name.equals("<clinit>") && !name.equals("<init>") && !mi.isPrivate() && !mi.isStatic() && !mi.isFinal() && !mi.isAbstract()) {
                        if (invokes.contains(clazz.getInternalName() + "." + name + mi.getDesc())) {
                            if (reachableMethods.contains(clazz.getInternalName() + "." + name + mi.getDesc())) {
                                mbs[mbIdx].addFunction(createLookup(mbs[mbIdx], ci, mi));
                            }
                        }
                    }
                }
            }
        }
        if (checkcasts.contains(clazz.getInternalName())) {
            mbs[mbIdx].addFunction(createCheckcast(mbs[mbIdx], clazz, typeInfo));
        }
        if (instanceofs.contains(clazz.getInternalName())) {
            mbs[mbIdx].addFunction(createInstanceof(mbs[mbIdx], clazz, typeInfo));
        }
    }
    config.getLogger().info("%d methods out of %d included in the executable", reachableMethodCount, totalMethodCount);
    List<File> objectFiles = new ArrayList<File>();
    generateMachineCode(config, mbs, objectFiles);
    for (Clazz clazz : linkClasses) {
        objectFiles.add(config.getOFile(clazz));
    }
    /*
         * Assemble the lines files for all linked classes into the module.
         */
    for (Clazz clazz : linkClasses) {
        File f = config.getLinesOFile(clazz);
        if (f.exists() && f.length() > 0) {
            objectFiles.add(f);
        }
    }
    config.getTarget().build(objectFiles);
}
Also used : HashMap(java.util.HashMap) CompilerPlugin(org.robovm.compiler.plugin.CompilerPlugin) Config(org.robovm.compiler.config.Config) NullConstant(org.robovm.compiler.llvm.NullConstant) StructureConstant(org.robovm.compiler.llvm.StructureConstant) IntegerConstant(org.robovm.compiler.llvm.IntegerConstant) Constant(org.robovm.compiler.llvm.Constant) ArrayConstant(org.robovm.compiler.llvm.ArrayConstant) ConstantBitcast(org.robovm.compiler.llvm.ConstantBitcast) ArrayList(java.util.ArrayList) Global(org.robovm.compiler.llvm.Global) HashTableGenerator(org.robovm.compiler.hash.HashTableGenerator) ModifiedUtf8HashFunction(org.robovm.compiler.hash.ModifiedUtf8HashFunction) ArrayConstantBuilder(org.robovm.compiler.llvm.ArrayConstantBuilder) ModifiedUtf8HashFunction(org.robovm.compiler.hash.ModifiedUtf8HashFunction) Function(org.robovm.compiler.llvm.Function) FunctionDeclaration(org.robovm.compiler.llvm.FunctionDeclaration) Random(java.util.Random) Unreachable(org.robovm.compiler.llvm.Unreachable) TreeSet(java.util.TreeSet) Clazz(org.robovm.compiler.clazz.Clazz) FunctionRef(org.robovm.compiler.llvm.FunctionRef) HashSet(java.util.HashSet) Path(org.robovm.compiler.clazz.Path) OS(org.robovm.compiler.config.OS) FunctionType(org.robovm.compiler.llvm.FunctionType) Arch(org.robovm.compiler.config.Arch) NullConstant(org.robovm.compiler.llvm.NullConstant) ClazzInfo(org.robovm.compiler.clazz.ClazzInfo) StructureConstantBuilder(org.robovm.compiler.llvm.StructureConstantBuilder) IntegerConstant(org.robovm.compiler.llvm.IntegerConstant) StructureConstant(org.robovm.compiler.llvm.StructureConstant) MethodInfo(org.robovm.compiler.clazz.MethodInfo) File(java.io.File) ConstantGetelementptr(org.robovm.compiler.llvm.ConstantGetelementptr)

Example 5 with Clazz

use of org.robovm.compiler.clazz.Clazz in project robovm by robovm.

the class MarshalerLookup method findMarshalers.

private void findMarshalers(SootClass sc, List<Marshaler> result, Set<String> visited, Set<String> seen, boolean searchBuiltins) {
    findMarshalersOnClasses(sc, result, visited, seen);
    findMarshalersOnInterfaces(sc, result, visited, seen);
    findMarshalersOnOuterClasses(sc, result, visited, seen);
    if (searchBuiltins) {
        Clazz builtinMarshalersClazz = config.getClazzes().load(BUILTIN_MARSHALERS);
        if (builtinMarshalersClazz != null) {
            findMarshalersOnClasses(builtinMarshalersClazz.getSootClass(), result, visited, seen);
        }
    }
}
Also used : Clazz(org.robovm.compiler.clazz.Clazz)

Aggregations

Clazz (org.robovm.compiler.clazz.Clazz)23 HashSet (java.util.HashSet)9 Test (org.junit.Test)6 Clazzes (org.robovm.compiler.clazz.Clazzes)6 Path (org.robovm.compiler.clazz.Path)6 LinkedHashSet (java.util.LinkedHashSet)5 Unreachable (org.robovm.compiler.llvm.Unreachable)5 File (java.io.File)4 IOException (java.io.IOException)3 TreeSet (java.util.TreeSet)3 Function (org.robovm.compiler.llvm.Function)3 FunctionRef (org.robovm.compiler.llvm.FunctionRef)3 ArrayList (java.util.ArrayList)2 HashMap (java.util.HashMap)2 ClassReader (org.objectweb.asm.ClassReader)2 ClassVisitor (org.objectweb.asm.ClassVisitor)2 MethodVisitor (org.objectweb.asm.MethodVisitor)2 ModuleBuilder (org.robovm.compiler.ModuleBuilder)2 ClazzInfo (org.robovm.compiler.clazz.ClazzInfo)2 Dependency (org.robovm.compiler.clazz.Dependency)2