nitg: Implemented polymorphic super calls for nitg-s and nitg-e
authorAlexandre Terrasa <alexandre@moz-code.org>
Tue, 10 Sep 2013 14:45:00 +0000 (10:45 -0400)
committerAlexandre Terrasa <alexandre@moz-code.org>
Tue, 10 Sep 2013 14:45:00 +0000 (10:45 -0400)
Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

src/layout_builders.nit
src/separate_compiler.nit
src/typing.nit
tests/sav/base_super_linext_raf.res
tests/sav/nitg-e/base_super_linext_raf.res [new file with mode: 0644]
tests/sav/nitg-s/base_super_linext_raf.res [new file with mode: 0644]
tests/sav/nitg/base_super_linext_raf.res [new file with mode: 0644]
tests/sav/niti/base_super_linext_raf.res [new file with mode: 0644]

index 73c9911..f7dc388 100644 (file)
@@ -60,12 +60,25 @@ interface TypingLayoutBuilder[E: Object]
 end
 
 # Layout builder dedicated to vft, attribute & VT tables
-interface PropertyLayoutBuilder[E: MProperty]
+interface PropertyLayoutBuilder[E: PropertyLayoutElement]
        # Build table layout for attributes, methods and virtual types
        # elements: the associative map between classes and properties to use in table layout
        fun build_layout(elements: Map[MClass, Set[E]]): Layout[E] is abstract
 end
 
+# Used to create a common ancestors to MProperty and MPropDef
+# Required for polymorphic calls
+# FIXME: there should be a better way
+interface PropertyLayoutElement end
+
+redef class MProperty
+       super PropertyLayoutElement
+end
+
+redef class MPropDef
+       super PropertyLayoutElement
+end
+
 # For resolution tables (generics)
 interface ResolutionLayoutBuilder
        # Build resolution table layout
@@ -179,7 +192,7 @@ class ResolutionBMizer
 end
 
 # Abstract Layout builder for mproperties using Binary Matrix (BM)
-class MPropertyBMizer[E: MProperty]
+class MPropertyBMizer[E: PropertyLayoutElement]
        super PropertyLayoutBuilder[E]
 
        var mmodule: MModule
@@ -375,7 +388,7 @@ class MClassColorer
 end
 
 # Abstract Layout builder for properties tables using coloration (CL)
-class MPropertyColorer[E: MProperty]
+class MPropertyColorer[E: PropertyLayoutElement]
        super PropertyLayoutBuilder[E]
 
        private var mmodule: MModule
@@ -665,7 +678,7 @@ class MClassHasher
 end
 
 # Abstract layout builder for properties tables using perfect hashing (PH)
-class MPropertyHasher[E: MProperty]
+class MPropertyHasher[E: PropertyLayoutElement]
        super PerfectHasher[MClass, E]
        super PropertyLayoutBuilder[E]
 
index fe0fc69..0606c4a 100644 (file)
@@ -106,6 +106,8 @@ end
 class SeparateCompiler
        super AbstractCompiler
 
+       redef type VISITOR: SeparateCompilerVisitor
+
        # The result of the RTA (used to know live types and methods)
        var runtime_type_analysis: RapidTypeAnalysis
 
@@ -115,7 +117,7 @@ class SeparateCompiler
 
        private var type_layout: nullable Layout[MType]
        private var resolution_layout: nullable Layout[MType]
-       protected var method_layout: nullable Layout[MMethod]
+       protected var method_layout: nullable Layout[PropertyLayoutElement]
        protected var attr_layout: nullable Layout[MAttribute]
 
        init(mainmodule: MModule, mmbuilder: ModelBuilder, runtime_type_analysis: RapidTypeAnalysis) do
@@ -194,24 +196,35 @@ class SeparateCompiler
        fun compile_color_consts(colors: Map[Object, Int]) do
                var v = new_visitor
                for m, c in colors do
-                       if color_consts_done.has(m) then continue
-                       if m isa MProperty then
-                               if modelbuilder.toolcontext.opt_inline_coloring_numbers.value then
-                                       self.provide_declaration(m.const_color, "#define {m.const_color} {c}")
-                               else
-                                       self.provide_declaration(m.const_color, "extern const int {m.const_color};")
-                                       v.add("const int {m.const_color} = {c};")
-                               end
-                       else if m isa MType then
-                               if modelbuilder.toolcontext.opt_inline_coloring_numbers.value then
-                                       self.provide_declaration(m.const_color, "#define {m.const_color} {c}")
-                               else
-                                       self.provide_declaration(m.const_color, "extern const int {m.const_color};")
-                                       v.add("const int {m.const_color} = {c};")
-                               end
+                       compile_color_const(v, m, c)
+               end
+       end
+
+       fun compile_color_const(v: SeparateCompilerVisitor, m: Object, color: Int) do
+               if color_consts_done.has(m) then return
+               if m isa MProperty then
+                       if modelbuilder.toolcontext.opt_inline_coloring_numbers.value then
+                               self.provide_declaration(m.const_color, "#define {m.const_color} {color}")
+                       else
+                               self.provide_declaration(m.const_color, "extern const int {m.const_color};")
+                               v.add("const int {m.const_color} = {color};")
+                       end
+               else if m isa MPropDef then
+                       if modelbuilder.toolcontext.opt_inline_coloring_numbers.value then
+                               self.provide_declaration(m.const_color, "#define {m.const_color} {color}")
+                       else
+                               self.provide_declaration(m.const_color, "extern const int {m.const_color};")
+                               v.add("const int {m.const_color} = {color};")
+                       end
+               else if m isa MType then
+                       if modelbuilder.toolcontext.opt_inline_coloring_numbers.value then
+                               self.provide_declaration(m.const_color, "#define {m.const_color} {color}")
+                       else
+                               self.provide_declaration(m.const_color, "extern const int {m.const_color};")
+                               v.add("const int {m.const_color} = {color};")
                        end
-                       color_consts_done.add(m)
                end
+               color_consts_done.add(m)
        end
 
        private var color_consts_done = new HashSet[Object]
@@ -221,7 +234,7 @@ class SeparateCompiler
                var mclasses = new HashSet[MClass].from(modelbuilder.model.mclasses)
 
                # Layouts
-               var method_layout_builder: PropertyLayoutBuilder[MMethod]
+               var method_layout_builder: PropertyLayoutBuilder[PropertyLayoutElement]
                var attribute_layout_builder: PropertyLayoutBuilder[MAttribute]
                #FIXME PH and BM layouts too slow for large programs
                #if modelbuilder.toolcontext.opt_bm_typing.value then
@@ -237,15 +250,15 @@ class SeparateCompiler
 
                var class_layout_builder = new MClassColorer(self.mainmodule)
                class_layout_builder.build_layout(mclasses)
-               method_layout_builder = new MPropertyColorer[MMethod](self.mainmodule, class_layout_builder)
+               method_layout_builder = new MPropertyColorer[PropertyLayoutElement](self.mainmodule, class_layout_builder)
                attribute_layout_builder = new MPropertyColorer[MAttribute](self.mainmodule, class_layout_builder)
                #end
 
                # lookup properties to build layout with
-               var mmethods = new HashMap[MClass, Set[MMethod]]
+               var mmethods = new HashMap[MClass, Set[PropertyLayoutElement]]
                var mattributes = new HashMap[MClass, Set[MAttribute]]
                for mclass in mclasses do
-                       mmethods[mclass] = new HashSet[MMethod]
+                       mmethods[mclass] = new HashSet[PropertyLayoutElement]
                        mattributes[mclass] = new HashSet[MAttribute]
                        for mprop in self.mainmodule.properties(mclass) do
                                if mprop isa MMethod then
@@ -256,29 +269,52 @@ class SeparateCompiler
                        end
                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
+               for mmethoddef in super_calls do
+                       var mclass = mmethoddef.mclassdef.mclass
+                       mmethods[mclass].add(mmethoddef)
+                       for descendant in mclass.in_hierarchy(self.mainmodule).smallers do
+                               mmethods[descendant].add(mmethoddef)
+                       end
+               end
+
                # methods coloration
-               var method_layout = method_layout_builder.build_layout(mmethods)
-               self.method_tables = build_method_tables(mclasses, method_layout)
+               self.method_layout = method_layout_builder.build_layout(mmethods)
+               self.method_tables = build_method_tables(mclasses, super_calls)
                self.compile_color_consts(method_layout.pos)
-               self.method_layout = method_layout
+
+               # attribute null color to dead supercalls
+               for mmodule in self.mainmodule.in_importation.greaters do
+                       for mclassdef in mmodule.mclassdefs do
+                               for mpropdef in mclassdef.mpropdefs do
+                                       if mpropdef.has_supercall then
+                                               compile_color_const(new_visitor, mpropdef, -1)
+                                       end
+                               end
+                       end
+               end
 
                # attributes coloration
-               var attr_layout = attribute_layout_builder.build_layout(mattributes)
-               self.attr_tables = build_attr_tables(mclasses, attr_layout)
+               self.attr_layout = attribute_layout_builder.build_layout(mattributes)
+               self.attr_tables = build_attr_tables(mclasses)
                self.compile_color_consts(attr_layout.pos)
-               self.attr_layout = attr_layout
        end
 
-       fun build_method_tables(mclasses: Set[MClass], layout: Layout[MProperty]): Map[MClass, Array[nullable MPropDef]] do
+       fun build_method_tables(mclasses: Set[MClass], super_calls: Set[MMethodDef]): Map[MClass, Array[nullable MPropDef]] do
+               var layout = self.method_layout
                var tables = new HashMap[MClass, Array[nullable MPropDef]]
                for mclass in mclasses do
                        var table = new Array[nullable MPropDef]
+                       var supercalls = new List[MMethodDef]
+
                        # first, fill table from parents by reverse linearization order
                        var parents = new Array[MClass]
                        if mainmodule.flatten_mclass_hierarchy.has(mclass) then
                                parents = mclass.in_hierarchy(mainmodule).greaters.to_a
                                self.mainmodule.linearize_mclasses(parents)
                        end
+
                        for parent in parents do
                                if parent == mclass then continue
                                for mproperty in self.mainmodule.properties(parent) do
@@ -295,6 +331,15 @@ class SeparateCompiler
                                                end
                                        end
                                end
+
+                               # lookup for super calls in super classes
+                               for mmethoddef in super_calls do
+                                       for mclassdef in parent.mclassdefs do
+                                               if mclassdef.mpropdefs.has(mmethoddef) then
+                                                       supercalls.add(mmethoddef)
+                                               end
+                                       end
+                               end
                        end
 
                        # then override with local properties
@@ -312,12 +357,33 @@ class SeparateCompiler
                                        end
                                end
                        end
+
+                       # lookup for super calls in local class
+                       for mmethoddef in super_calls do
+                               for mclassdef in mclass.mclassdefs do
+                                       if mclassdef.mpropdefs.has(mmethoddef) then
+                                               supercalls.add(mmethoddef)
+                                       end
+                               end
+                       end
+                       # insert super calls in table according to receiver
+                       for supercall in supercalls do
+                               var color = layout.pos[supercall]
+                               if table.length <= color then
+                                       for i in [table.length .. color[ do
+                                               table[i] = null
+                                       end
+                               end
+                               var mmethoddef = supercall.lookup_next_definition(self.mainmodule, mclass.intro.bound_mtype)
+                               table[color] = mmethoddef
+                       end
                        tables[mclass] = table
                end
                return tables
        end
 
-       fun build_attr_tables(mclasses: Set[MClass], layout: Layout[MProperty]): Map[MClass, Array[nullable MPropDef]] do
+       fun build_attr_tables(mclasses: Set[MClass]): Map[MClass, Array[nullable MPropDef]] do
+               var layout = self.attr_layout
                var tables = new HashMap[MClass, Array[nullable MPropDef]]
                for mclass in mclasses do
                        var table = new Array[nullable MPropDef]
@@ -907,6 +973,12 @@ 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
@@ -935,7 +1007,6 @@ class SeparateCompilerVisitor
                var recv = arguments.first
                s.append("val*")
                ss.append("{recv}")
-               self.varargize(mmethod.intro, mmethod.intro.msignature.as(not null), arguments)
                for i in [0..msignature.arity[ do
                        var a = arguments[i+1]
                        var t = msignature.mparameters[i].mtype
@@ -995,8 +1066,8 @@ class SeparateCompilerVisitor
 
                var r
                if ret == null then r = "void" else r = ret.ctype
-               self.require_declaration(mmethod.const_color)
-               var call = "(({r} (*)({s}))({arguments.first}->class->vft[{mmethod.const_color}]))({ss}) /* {mmethod} on {arguments.first.inspect}*/"
+               self.require_declaration(const_color)
+               var call = "(({r} (*)({s}))({arguments.first}->class->vft[{const_color}]))({ss}) /* {mmethod} on {arguments.first.inspect}*/"
 
                if res != null then
                        self.add("{res} = {call};")
@@ -1055,11 +1126,9 @@ class SeparateCompilerVisitor
                return res
        end
 
-       redef fun supercall(m: MMethodDef, recvtype: MClassType, args: Array[RuntimeVariable]): nullable RuntimeVariable
+       redef fun supercall(m: MMethodDef, recvtype: MClassType, arguments: Array[RuntimeVariable]): nullable RuntimeVariable
        do
-               # FIXME implements a polymorphic access in tables
-               m = m.lookup_next_definition(m.mclassdef.mmodule, m.mclassdef.bound_mtype)
-               return self.call(m, recvtype, args)
+               return table_send(m.mproperty, arguments, m.const_color)
        end
 
        redef fun vararg_instance(mpropdef, recv, varargs, elttype)
@@ -1709,3 +1778,7 @@ end
 redef class MProperty
        fun const_color: String do return "COLOR_{c_name}"
 end
+
+redef class MPropDef
+       fun const_color: String do return "COLOR_{c_name}"
+end
index be3b2b0..be7b9ea 100644 (file)
@@ -27,6 +27,11 @@ redef class ToolContext
        var typing_phase: Phase = new TypingPhase(self, [flow_phase, modelize_property_phase, local_var_init_phase])
 end
 
+redef class MPropDef
+       # Does the MPropDef contains a call to super or a call of a super-constructor?
+       var has_supercall: Bool = false
+end
+
 private class TypingPhase
        super Phase
        redef fun process_npropdef(npropdef) do npropdef.do_typing(toolcontext.modelbuilder)
@@ -1452,6 +1457,7 @@ redef class ASuperExpr
                end
                self.mtype = msignature.return_mtype
                self.is_typed = true
+               v.mpropdef.has_supercall = true
        end
 
        private fun process_superinit(v: TypeVisitor)
index 4c73f6d..ee284c0 100644 (file)
@@ -1,8 +1,8 @@
 a[A]
 Aa
-b[B[a[A]]]
-AaBb
-c[C[a[A]]]
-AaCc
-d[D[c[C[b[B[a[A]]]]]]]
-AaBbCcDd
+b[B[A]]
+ABb
+c[C[A]]
+ACc
+d[D[C[B[A]]]]
+ABCDd
diff --git a/tests/sav/nitg-e/base_super_linext_raf.res b/tests/sav/nitg-e/base_super_linext_raf.res
new file mode 100644 (file)
index 0000000..4c73f6d
--- /dev/null
@@ -0,0 +1,8 @@
+a[A]
+Aa
+b[B[a[A]]]
+AaBb
+c[C[a[A]]]
+AaCc
+d[D[c[C[b[B[a[A]]]]]]]
+AaBbCcDd
diff --git a/tests/sav/nitg-s/base_super_linext_raf.res b/tests/sav/nitg-s/base_super_linext_raf.res
new file mode 100644 (file)
index 0000000..4c73f6d
--- /dev/null
@@ -0,0 +1,8 @@
+a[A]
+Aa
+b[B[a[A]]]
+AaBb
+c[C[a[A]]]
+AaCc
+d[D[c[C[b[B[a[A]]]]]]]
+AaBbCcDd
diff --git a/tests/sav/nitg/base_super_linext_raf.res b/tests/sav/nitg/base_super_linext_raf.res
new file mode 100644 (file)
index 0000000..4c73f6d
--- /dev/null
@@ -0,0 +1,8 @@
+a[A]
+Aa
+b[B[a[A]]]
+AaBb
+c[C[a[A]]]
+AaCc
+d[D[c[C[b[B[a[A]]]]]]]
+AaBbCcDd
diff --git a/tests/sav/niti/base_super_linext_raf.res b/tests/sav/niti/base_super_linext_raf.res
new file mode 100644 (file)
index 0000000..4c73f6d
--- /dev/null
@@ -0,0 +1,8 @@
+a[A]
+Aa
+b[B[a[A]]]
+AaBb
+c[C[a[A]]]
+AaCc
+d[D[c[C[b[B[a[A]]]]]]]
+AaBbCcDd