rta: use callsites to do the analysis
[nit.git] / src / separate_compiler.nit
index ea4e00f..e553259 100644 (file)
@@ -18,6 +18,7 @@ module separate_compiler
 import abstract_compiler
 import layout_builders
 import rapid_type_analysis
+import collect_super_sends
 
 # Add separate compiler specific options
 redef class ToolContext
@@ -56,7 +57,7 @@ redef class ToolContext
 end
 
 redef class ModelBuilder
-       fun run_separate_compiler(mainmodule: MModule, runtime_type_analysis: RapidTypeAnalysis)
+       fun run_separate_compiler(mainmodule: MModule, runtime_type_analysis: nullable RapidTypeAnalysis)
        do
                var time0 = get_time
                self.toolcontext.info("*** GENERATING C ***", 1)
@@ -109,7 +110,7 @@ class SeparateCompiler
        redef type VISITOR: SeparateCompilerVisitor
 
        # The result of the RTA (used to know live types and methods)
-       var runtime_type_analysis: RapidTypeAnalysis
+       var runtime_type_analysis: nullable RapidTypeAnalysis
 
        private var undead_types: Set[MType] = new HashSet[MType]
        private var partial_types: Set[MType] = new HashSet[MType]
@@ -120,7 +121,7 @@ class SeparateCompiler
        protected var method_layout: nullable Layout[PropertyLayoutElement]
        protected var attr_layout: nullable Layout[MAttribute]
 
-       init(mainmodule: MModule, mmbuilder: ModelBuilder, runtime_type_analysis: RapidTypeAnalysis) do
+       init(mainmodule: MModule, mmbuilder: ModelBuilder, runtime_type_analysis: nullable RapidTypeAnalysis) do
                super(mainmodule, mmbuilder)
                var file = new_file("nit.common")
                self.header = new CodeWriter(file)
@@ -270,7 +271,12 @@ class SeparateCompiler
                end
 
                # lookup super calls and add it to the list of mmethods to build layout with
-               var super_calls = runtime_type_analysis.live_super_sends
+               var super_calls
+               if runtime_type_analysis != null then
+                       super_calls = runtime_type_analysis.live_super_sends
+               else
+                       super_calls = modelbuilder.collect_super_sends
+               end
                for mmethoddef in super_calls do
                        var mclass = mmethoddef.mclassdef.mclass
                        mmethods[mclass].add(mmethoddef)
@@ -722,7 +728,7 @@ class SeparateCompiler
                var attrs = self.attr_tables[mclass]
                var v = new_visitor
 
-               var is_dead = not runtime_type_analysis.live_classes.has(mclass) and mtype.ctype == "val*" and mclass.name != "NativeArray"
+               var is_dead = runtime_type_analysis != null and not runtime_type_analysis.live_classes.has(mclass) and mtype.ctype == "val*" and mclass.name != "NativeArray"
 
                v.add_decl("/* runtime class {c_name} */")
 
@@ -814,8 +820,6 @@ class SeparateCompiler
                        v.add("return {res};")
                end
                v.add("\}")
-
-               generate_check_init_instance(mtype)
        end
 
        # Add a dynamic test to ensure that the type referenced by `t` is a live type
@@ -831,24 +835,6 @@ class SeparateCompiler
                v.add("\}")
        end
 
-       redef fun generate_check_init_instance(mtype)
-       do
-               if self.modelbuilder.toolcontext.opt_no_check_initialization.value then return
-
-               var v = self.new_visitor
-               var c_name = mtype.mclass.c_name
-               var res = new RuntimeVariable("self", mtype, mtype)
-               self.provide_declaration("CHECK_NEW_{c_name}", "void CHECK_NEW_{c_name}({mtype.ctype});")
-               v.add_decl("/* allocate {mtype} */")
-               v.add_decl("void CHECK_NEW_{c_name}({mtype.ctype} {res}) \{")
-               if runtime_type_analysis.live_classes.has(mtype.mclass) then
-                       self.generate_check_attr(v, res, mtype)
-               else
-                       v.add_abort("{mtype.mclass} is DEAD")
-               end
-               v.add("\}")
-       end
-
        redef fun new_visitor do return new SeparateCompilerVisitor(self)
 
        # Stats
@@ -943,7 +929,7 @@ class SeparateCompilerVisitor
                else if mtype.ctype == "val*" then
                        var valtype = value.mtype.as(MClassType)
                        var res = self.new_var(mtype)
-                       if not compiler.runtime_type_analysis.live_types.has(valtype) then
+                       if compiler.runtime_type_analysis != null and not compiler.runtime_type_analysis.live_types.has(valtype) then
                                self.add("/*no autobox from {value.mtype} to {mtype}: {value.mtype} is not live! */")
                                self.add("printf(\"Dead code executed!\\n\"); show_backtrace(1);")
                                return res
@@ -974,11 +960,7 @@ class SeparateCompilerVisitor
        redef fun send(mmethod, arguments)
        do
                self.varargize(mmethod.intro, mmethod.intro.msignature.as(not null), arguments)
-               return table_send(mmethod, arguments, mmethod.const_color)
-       end
 
-       private fun table_send(mmethod: MMethod, arguments: Array[RuntimeVariable], const_color: String): nullable RuntimeVariable
-       do
                if arguments.first.mcasttype.ctype != "val*" then
                        # In order to shortcut the primitive, we need to find the most specific method
                        # Howverr, because of performance (no flattening), we always work on the realmainmodule
@@ -989,6 +971,11 @@ class SeparateCompilerVisitor
                        return res
                end
 
+               return table_send(mmethod, arguments, mmethod.const_color)
+       end
+
+       private fun table_send(mmethod: MMethod, arguments: Array[RuntimeVariable], const_color: String): nullable RuntimeVariable
+       do
                var res: nullable RuntimeVariable
                var msignature = mmethod.intro.msignature.resolve_for(mmethod.intro.mclassdef.bound_mtype, mmethod.intro.mclassdef.bound_mtype, mmethod.intro.mclassdef.mmodule, true)
                var ret = msignature.return_mtype
@@ -1128,6 +1115,15 @@ class SeparateCompilerVisitor
 
        redef fun supercall(m: MMethodDef, recvtype: MClassType, arguments: Array[RuntimeVariable]): nullable RuntimeVariable
        do
+               if arguments.first.mcasttype.ctype != "val*" then
+                       # In order to shortcut the primitive, we need to find the most specific method
+                       # However, because of performance (no flattening), we always work on the realmainmodule
+                       var main = self.compiler.mainmodule
+                       self.compiler.mainmodule = self.compiler.realmainmodule
+                       var res = self.monomorphic_super_send(m, recvtype, arguments)
+                       self.compiler.mainmodule = main
+                       return res
+               end
                return table_send(m.mproperty, arguments, m.const_color)
        end
 
@@ -1276,13 +1272,6 @@ class SeparateCompilerVisitor
                return self.new_expr("NEW_{mtype.mclass.c_name}(&type_{mtype.c_name})", mtype)
        end
 
-       redef fun check_init_instance(value, mtype)
-       do
-               if self.compiler.modelbuilder.toolcontext.opt_no_check_initialization.value then return
-               self.require_declaration("CHECK_NEW_{mtype.mclass.c_name}")
-               self.add("CHECK_NEW_{mtype.mclass.c_name}({value});")
-       end
-
        redef fun type_test(value, mtype, tag)
        do
                self.add("/* {value.inspect} isa {mtype} */")
@@ -1405,6 +1394,8 @@ class SeparateCompilerVisitor
                self.add_decl("const char* {res};")
                if value.mtype.ctype == "val*" then
                        self.add "{res} = {value} == NULL ? \"null\" : {value}->type->name;"
+               else if value.mtype isa MClassType and value.mtype.as(MClassType).mclass.kind == extern_kind then
+                       self.add "{res} = \"{value.mtype.as(MClassType).mclass}\";"
                else
                        self.require_declaration("type_{value.mtype.c_name}")
                        self.add "{res} = type_{value.mtype.c_name}.name;"
@@ -1531,7 +1522,6 @@ class SeparateCompilerVisitor
                        self.add("((struct instance_{nclass.c_name}*){nat})->values[{i}] = (val*) {r};")
                end
                self.send(self.get_property("with_native", arrayclass.intro.bound_mtype), [res, nat, length])
-               self.check_init_instance(res, arraytype)
                self.add("\}")
                return res
        end