Merge: Enforce namespace rules
[nit.git] / src / compiler / separate_compiler.nit
index 7bb2bc1..1f1cf67 100644 (file)
@@ -90,12 +90,55 @@ redef class ModelBuilder
                self.toolcontext.info("*** GENERATING C ***", 1)
 
                var compiler = new SeparateCompiler(mainmodule, self, runtime_type_analysis)
+               compiler.do_compilation
+               compiler.display_stats
+
+               var time1 = get_time
+               self.toolcontext.info("*** END GENERATING C: {time1-time0} ***", 2)
+               write_and_make(compiler)
+       end
+
+       # Count number of invocations by VFT
+       private var nb_invok_by_tables = 0
+       # Count number of invocations by direct call
+       private var nb_invok_by_direct = 0
+       # Count number of invocations by inlining
+       private var nb_invok_by_inline = 0
+end
+
+# Singleton that store the knowledge about the separate compilation process
+class SeparateCompiler
+       super AbstractCompiler
+
+       redef type VISITOR: SeparateCompilerVisitor
+
+       # The result of the RTA (used to know live types and methods)
+       var runtime_type_analysis: nullable RapidTypeAnalysis
+
+       private var undead_types: Set[MType] = new HashSet[MType]
+       private var live_unresolved_types: Map[MClassDef, Set[MType]] = new HashMap[MClassDef, HashSet[MType]]
+
+       private var type_ids: Map[MType, Int] is noinit
+       private var type_colors: Map[MType, Int] is noinit
+       private var opentype_colors: Map[MType, Int] is noinit
+       protected var method_colors: Map[PropertyLayoutElement, Int] is noinit
+       protected var attr_colors: Map[MAttribute, Int] is noinit
+
+       init do
+               var file = new_file("nit.common")
+               self.header = new CodeWriter(file)
+               self.compile_box_kinds
+       end
+
+       redef fun do_compilation
+       do
+               var compiler = self
                compiler.compile_header
 
                var c_name = mainmodule.c_name
 
                # compile class structures
-               self.toolcontext.info("Property coloring", 2)
+               modelbuilder.toolcontext.info("Property coloring", 2)
                compiler.new_file("{c_name}.classes")
                compiler.do_property_coloring
                for m in mainmodule.in_importation.greaters do
@@ -113,14 +156,22 @@ redef class ModelBuilder
 
                # compile methods
                for m in mainmodule.in_importation.greaters do
-                       self.toolcontext.info("Generate C for module {m.full_name}", 2)
+                       modelbuilder.toolcontext.info("Generate C for module {m.full_name}", 2)
                        compiler.new_file("{m.c_name}.sep")
                        compiler.compile_module_to_c(m)
                end
 
                # compile live & cast type structures
-               self.toolcontext.info("Type coloring", 2)
+               modelbuilder.toolcontext.info("Type coloring", 2)
                compiler.new_file("{c_name}.types")
+               compiler.compile_types
+       end
+
+       # Color and compile type structures and cast information
+       fun compile_types
+       do
+               var compiler = self
+
                var mtypes = compiler.do_type_coloring
                for t in mtypes do
                        compiler.compile_type_to_c(t)
@@ -131,43 +182,6 @@ redef class ModelBuilder
                        compiler.compile_type_to_c(t)
                end
 
-               compiler.display_stats
-
-               var time1 = get_time
-               self.toolcontext.info("*** END GENERATING C: {time1-time0} ***", 2)
-               write_and_make(compiler)
-       end
-
-       # Count number of invocations by VFT
-       private var nb_invok_by_tables = 0
-       # Count number of invocations by direct call
-       private var nb_invok_by_direct = 0
-       # Count number of invocations by inlining
-       private var nb_invok_by_inline = 0
-end
-
-# Singleton that store the knowledge about the separate compilation process
-class SeparateCompiler
-       super AbstractCompiler
-
-       redef type VISITOR: SeparateCompilerVisitor
-
-       # The result of the RTA (used to know live types and methods)
-       var runtime_type_analysis: nullable RapidTypeAnalysis
-
-       private var undead_types: Set[MType] = new HashSet[MType]
-       private var live_unresolved_types: Map[MClassDef, Set[MType]] = new HashMap[MClassDef, HashSet[MType]]
-
-       private var type_ids: Map[MType, Int] is noinit
-       private var type_colors: Map[MType, Int] is noinit
-       private var opentype_colors: Map[MType, Int] is noinit
-       protected var method_colors: Map[PropertyLayoutElement, Int] is noinit
-       protected var attr_colors: Map[MAttribute, Int] is noinit
-
-       init do
-               var file = new_file("nit.common")
-               self.header = new CodeWriter(file)
-               self.compile_box_kinds
        end
 
        redef fun compile_header_structs do
@@ -1063,8 +1077,8 @@ class SeparateCompilerVisitor
        do
                var rta = compiler.runtime_type_analysis
                var mmethod = callsite.mproperty
-               # TODO: Inlining of new-style constructors
-               if compiler.modelbuilder.toolcontext.opt_direct_call_monomorph.value and rta != null and not mmethod.is_root_init then
+               # TODO: Inlining of new-style constructors with initializers
+               if compiler.modelbuilder.toolcontext.opt_direct_call_monomorph.value and rta != null and callsite.mpropdef.initializers.is_empty then
                        var tgs = rta.live_targets(callsite)
                        if tgs.length == 1 then
                                # DIRECT CALL
@@ -1112,10 +1126,10 @@ class SeparateCompilerVisitor
                var res: nullable RuntimeVariable = null
                var recv = arguments.first
                var consider_null = not self.compiler.modelbuilder.toolcontext.opt_no_check_null.value or mmethod.name == "==" or mmethod.name == "!="
-               var maybenull = recv.mcasttype isa MNullableType and consider_null
+               var maybenull = (recv.mcasttype isa MNullableType or recv.mcasttype isa MNullType) and consider_null
                if maybenull then
                        self.add("if ({recv} == NULL) \{")
-                       if mmethod.name == "==" then
+                       if mmethod.name == "==" or mmethod.name == "is_same_instance" then
                                res = self.new_var(bool_type)
                                var arg = arguments[1]
                                if arg.mcasttype isa MNullableType then
@@ -1142,15 +1156,15 @@ class SeparateCompilerVisitor
                else
                        self.add("\{")
                end
-               if not self.compiler.modelbuilder.toolcontext.opt_no_shortcut_equate.value and (mmethod.name == "==" or mmethod.name == "!=") then
-                       if res == null then res = self.new_var(bool_type)
-                       # Recv is not null, thus is arg is, it is easy to conclude (and respect the invariants)
+               if not self.compiler.modelbuilder.toolcontext.opt_no_shortcut_equate.value and (mmethod.name == "==" or mmethod.name == "!=" or mmethod.name == "is_same_instance") then
+                       # Recv is not null, thus if arg is, it is easy to conclude (and respect the invariants)
                        var arg = arguments[1]
                        if arg.mcasttype isa MNullType then
-                               if mmethod.name == "==" then
-                                       self.add("{res} = 0; /* arg is null but recv is not */")
-                               else
+                               if res == null then res = self.new_var(bool_type)
+                               if mmethod.name == "!=" then
                                        self.add("{res} = 1; /* arg is null and recv is not */")
+                               else # `==` and `is_same_instance`
+                                       self.add("{res} = 0; /* arg is null but recv is not */")
                                end
                                self.add("\}") # closes the null case
                                self.add("if (0) \{") # what follow is useless, CC will drop it