Merge: Do not compile dead modules
authorJean Privat <jean@pryen.org>
Thu, 18 Jun 2015 03:09:33 +0000 (23:09 -0400)
committerJean Privat <jean@pryen.org>
Thu, 18 Jun 2015 03:09:33 +0000 (23:09 -0400)
Separate compilation implies that a module is compiled independently of its clients.
This point ensure us that the recompilation of programs is fast since only modified modules need to be recompiled and that modules used by multiples clients need to be compiled only once.

Unfortunately, currently an already compiled module need to still to be fully compiled in C on each compilation (avoiding doing it is a very complex matter). Fortunately, most of the compilation time is spend by the C compiler (especially when #1498) and this time is safely decimated by ccache.

However, a thing that some modules are imported by programs (thus provide declarations, introductions, importations) but are only made of method definitions that will never be executed by the program. Such a module is called a *dead* module and our static analysis RTA can approximate them.
So, now, the generation of C code for such a module is skipped (and its associated C compilation, obviously)

This will benefit mostly small programs that imports standard and other libraries but only use a small portion of them. Eg: programs in `tests/` or in `examples/rossetacode`.

For numbers, lets try with `time ./tests.sh ../examples/rosettacode/*.nit` to test the 32 (currently) programs.

* before: 30s
* after: 21s

I hope that CI servers will like what we, human masters, do for them!

Pull-Request: #1509
Reviewed-by: Alexis Laferrière <alexis.laf@xymus.net>
Reviewed-by: Romain Chanoir <chanoir.romain@courrier.uqam.ca>

src/compiler/separate_compiler.nit
src/rapid_type_analysis.nit

index e07f125..b1e08c8 100644 (file)
@@ -2209,13 +2209,18 @@ class SeparateRuntimeFunction
        # The C type for the function pointer.
        var c_funptrtype: String is lazy do return "{c_ret}(*){c_sig}"
 
-       # The arguments, as generated by `compile_to_c`
-       private var arguments: Array[RuntimeVariable] is noinit
-
        redef fun compile_to_c(compiler)
        do
                var mmethoddef = self.mmethoddef
 
+               var sig = "{c_ret} {c_name}{c_sig}"
+               compiler.provide_declaration(self.c_name, "{sig} __attribute__((weak));")
+
+               var rta = compiler.as(SeparateCompiler).runtime_type_analysis
+               if rta != null and not rta.live_mmodules.has(mmethoddef.mclassdef.mmodule) then
+                       return
+               end
+
                var recv = self.mmethoddef.mclassdef.bound_mtype
                var v = compiler.new_visitor
                var selfvar = new RuntimeVariable("self", called_recv, recv)
@@ -2226,12 +2231,7 @@ class SeparateRuntimeFunction
                var msignature = called_signature
                var ret = called_signature.return_mtype
 
-               var sig = new FlatBuffer
                var comment = new FlatBuffer
-               sig.append(c_ret)
-               sig.append(" ")
-               sig.append(self.c_name)
-               sig.append(c_sig)
                comment.append("({selfvar}: {selfvar.mtype}")
                arguments.add(selfvar)
                for i in [0..msignature.arity[ do
@@ -2247,8 +2247,6 @@ class SeparateRuntimeFunction
                if ret != null then
                        comment.append(": {ret}")
                end
-               compiler.provide_declaration(self.c_name, "{sig};")
-               self.arguments = arguments.to_a
 
                v.add_decl("/* method {self} for {comment} */")
                v.add_decl("{sig} \{")
@@ -2281,8 +2279,10 @@ class SeparateRuntimeFunction
        fun compile_trampolines(compiler: SeparateCompiler)
        do
                var recv = self.mmethoddef.mclassdef.bound_mtype
-               var selfvar = arguments.first
+               var selfvar = new RuntimeVariable("self", called_recv, recv)
                var ret = called_signature.return_mtype
+               var arguments = ["self"]
+               for i in [0..called_signature.arity[ do arguments.add "p{i}"
 
                if mmethoddef.is_intro and not recv.is_c_primitive then
                        var m = mmethoddef.mproperty
index 365f6a4..05e2332 100644 (file)
@@ -82,6 +82,10 @@ class RapidTypeAnalysis
        # Live methods.
        var live_methods = new HashSet[MMethod]
 
+       # Live mmodules.
+       # Those with a live method definitions (see `live_methoddefs`)
+       var live_mmodules = new HashSet[MModule]
+
        # Live callsites.
        var live_callsites = new HashSet[CallSite]
 
@@ -389,6 +393,7 @@ class RapidTypeAnalysis
        do
                if live_methoddefs.has(mpropdef) then return
                live_methoddefs.add(mpropdef)
+               live_mmodules.add(mpropdef.mclassdef.mmodule)
                todo.add(mpropdef)
 
                var mproperty = mpropdef.mproperty