Layout_builders: introduce posets for better performances
authorAlexandre Terrasa <alexandre@moz-code.org>
Wed, 7 Aug 2013 02:57:48 +0000 (22:57 -0400)
committerAlexandre Terrasa <alexandre@moz-code.org>
Wed, 7 Aug 2013 02:57:48 +0000 (22:57 -0400)
    Stats for nitg ./nitg.nit
    before:
0:21.23 elapsed,
20.68 user,
0.64 system

    after:
0:18.50 elapsed,
17.97 user,
0.62 system

Average on 5 samples collected with GNU time.

Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

src/abstract_compiler.nit
src/layout_builders.nit
src/model/model.nit
src/separate_compiler.nit
src/separate_erasure_compiler.nit

index 20ebe59..c33cdc6 100644 (file)
@@ -2384,208 +2384,25 @@ redef class Array[E]
 end
 
 redef class MModule
-
-       # Return a linearization of a set of mtypes
-       fun linearize_mtypes(mtypes: Set[MType]): Array[MType] do
-               var lin = new Array[MType].from(mtypes)
-               var sorter = new TypeSorter(self)
-               sorter.sort(lin)
-               return lin
-       end
-
-       # Return a reverse linearization of a set of mtypes
-       fun reverse_linearize_mtypes(mtypes: Set[MType]): Array[MType] do
-               var lin = new Array[MType].from(mtypes)
-               var sorter = new ReverseTypeSorter(self)
-               sorter.sort(lin)
-               return lin
-       end
-
-       # Return super types of a `mtype` in `self`
-       fun super_mtypes(mtype: MType, mtypes: Set[MType]): Set[MType] do
-               if not self.super_mtypes_cache.has_key(mtype) then
-                       var supers = new HashSet[MType]
-                       for otype in mtypes do
-                               if otype == mtype then continue
-                               if mtype.is_subtype(self, null, otype) then
-                                       supers.add(otype)
-                               end
-                       end
-                       self.super_mtypes_cache[mtype] = supers
-               end
-               return self.super_mtypes_cache[mtype]
-       end
-
-       private var super_mtypes_cache: Map[MType, Set[MType]] = new HashMap[MType, Set[MType]]
-
-       # Return all sub mtypes (directs and indirects) of a `mtype` in `self`
-       fun sub_mtypes(mtype: MType, mtypes: Set[MType]): Set[MType] do
-               if not self.sub_mtypes_cache.has_key(mtype) then
-                       var subs = new HashSet[MType]
-                       for otype in mtypes do
-                               if otype == mtype then continue
-                               if otype.is_subtype(self, null, mtype) then
-                                       subs.add(otype)
-                               end
-                       end
-                       self.sub_mtypes_cache[mtype] = subs
-               end
-               return self.sub_mtypes_cache[mtype]
-       end
-
-       private var sub_mtypes_cache: Map[MType, Set[MType]] = new HashMap[MType, Set[MType]]
-
-       # Return a linearization of a set of mclasses
-       fun linearize_mclasses_2(mclasses: Set[MClass]): Array[MClass] do
-               var lin = new Array[MClass].from(mclasses)
-               var sorter = new ClassSorter(self)
-               sorter.sort(lin)
-               return lin
-       end
-
-       # Return a reverse linearization of a set of mtypes
-       fun reverse_linearize_mclasses(mclasses: Set[MClass]): Array[MClass] do
-               var lin = new Array[MClass].from(mclasses)
-               var sorter = new ReverseClassSorter(self)
-               sorter.sort(lin)
-               return lin
-       end
-
-       # Return all super mclasses (directs and indirects) of a `mclass` in `self`
-       fun super_mclasses(mclass: MClass): Set[MClass] do
-               if not self.super_mclasses_cache.has_key(mclass) then
-                       var supers = new HashSet[MClass]
-                       if self.flatten_mclass_hierarchy.has(mclass) then
-                               for sup in self.flatten_mclass_hierarchy[mclass].greaters do
-                                       if sup == mclass then continue
-                                       supers.add(sup)
-                               end
-                       end
-                       self.super_mclasses_cache[mclass] = supers
-               end
-               return self.super_mclasses_cache[mclass]
-       end
-
-       private var super_mclasses_cache: Map[MClass, Set[MClass]] = new HashMap[MClass, Set[MClass]]
-
-       # Return all parents of a `mclass` in `self`
-       fun parent_mclasses(mclass: MClass): Set[MClass] do
-               if not self.parent_mclasses_cache.has_key(mclass) then
-                       var parents = new HashSet[MClass]
-                       if self.flatten_mclass_hierarchy.has(mclass) then
-                               for sup in self.flatten_mclass_hierarchy[mclass].direct_greaters do
-                                       if sup == mclass then continue
-                                       parents.add(sup)
-                               end
-                       end
-                       self.parent_mclasses_cache[mclass] = parents
-               end
-               return self.parent_mclasses_cache[mclass]
-       end
-
-       private var parent_mclasses_cache: Map[MClass, Set[MClass]] = new HashMap[MClass, Set[MClass]]
-
-       # Return all sub mclasses (directs and indirects) of a `mclass` in `self`
-       fun sub_mclasses(mclass: MClass): Set[MClass] do
-               if not self.sub_mclasses_cache.has_key(mclass) then
-                       var subs = new HashSet[MClass]
-                       if self.flatten_mclass_hierarchy.has(mclass) then
-                               for sub in self.flatten_mclass_hierarchy[mclass].smallers do
-                                       if sub == mclass then continue
-                                       subs.add(sub)
-                               end
-                       end
-                       self.sub_mclasses_cache[mclass] = subs
-               end
-               return self.sub_mclasses_cache[mclass]
-       end
-
-       private var sub_mclasses_cache: Map[MClass, Set[MClass]] = new HashMap[MClass, Set[MClass]]
-
        # All 'mproperties' associated to all 'mclassdefs' of `mclass`
        fun properties(mclass: MClass): Set[MProperty] do
                if not self.properties_cache.has_key(mclass) then
                        var properties = new HashSet[MProperty]
-                       var parents = self.super_mclasses(mclass)
+                       var parents = new Array[MClass]
+                       if self.flatten_mclass_hierarchy.has(mclass) then
+                               parents.add_all(mclass.in_hierarchy(self).direct_greaters)
+                       end
                        for parent in parents do
                                properties.add_all(self.properties(parent))
                        end
-
                        for mclassdef in mclass.mclassdefs do
-                               for mpropdef in mclassdef.mpropdefs do
-                                       properties.add(mpropdef.mproperty)
+                               for mprop in mclassdef.intro_mproperties do
+                                       properties.add(mprop)
                                end
                        end
                        self.properties_cache[mclass] = properties
                end
                return properties_cache[mclass]
        end
-
        private var properties_cache: Map[MClass, Set[MProperty]] = new HashMap[MClass, Set[MProperty]]
 end
-
-# A sorter for linearize list of types
-private class TypeSorter
-       super AbstractSorter[MType]
-
-       private var mmodule: MModule
-
-       init(mmodule: MModule) do self.mmodule = mmodule
-
-       redef fun compare(a, b) do
-               if a == b then
-                       return 0
-               else if a.is_subtype(self.mmodule, null, b) then
-                       return -1
-               end
-               return 1
-       end
-end
-
-# A sorter for reverse linearization
-private class ReverseTypeSorter
-       super TypeSorter
-
-       init(mmodule: MModule) do end
-
-       redef fun compare(a, b) do
-               if a == b then
-                       return 0
-               else if a.is_subtype(self.mmodule, null, b) then
-                       return 1
-               end
-               return -1
-       end
-end
-
-# A sorter for linearize list of classes
-private class ClassSorter
-       super AbstractSorter[MClass]
-
-       var mmodule: MModule
-
-       redef fun compare(a, b) do
-               if a == b then
-                       return 0
-               else if self.mmodule.flatten_mclass_hierarchy.has(a) and self.mmodule.flatten_mclass_hierarchy[a].greaters.has(b) then
-                       return -1
-               end
-               return 1
-       end
-end
-
-# A sorter for reverse linearization
-private class ReverseClassSorter
-       super AbstractSorter[MClass]
-
-       var mmodule: MModule
-
-       redef fun compare(a, b) do
-               if a == b then
-                       return 0
-               else if self.mmodule.flatten_mclass_hierarchy.has(a) and self.mmodule.flatten_mclass_hierarchy[a].greaters.has(b) then
-                       return 1
-               end
-               return -1
-       end
-end
index f8dc94c..201ebc1 100644 (file)
@@ -54,6 +54,9 @@ interface TypingLayoutBuilder[E: Object]
        # Build typing table layout
        # elements: the set of elements (classes or types) used in typing tables
        fun build_layout(elements: Set[E]): Layout[E] is abstract
+       # Get the poset used for table layout construction
+       # REQUIRE: build_layout
+       fun poset: nullable POSet[E] is abstract
 end
 
 # Layout builder dedicated to vft, attribute & VT tables
@@ -70,23 +73,67 @@ interface ResolutionLayoutBuilder
        fun build_layout(elements: Map[MClassType, Set[MType]]): Layout[MType] is abstract
 end
 
+# POSet builders
+
+# A POSet builder build a poset for a set of MType or MClass
+# the resulting poset is used by the layout builders
+private abstract class POSetBuilder[E: Object]
+       private var mmodule: MModule
+       init(mmodule: MModule) do self.mmodule = mmodule
+       # Build the poset from `elements`
+       private fun build_poset(elements: Set[E]): POSet[E] is abstract
+end
+
+# A TypingLayoutBuilder used for MType based typing
+# such as in separate compilers
+private class MTypePOSetBuilder
+       super POSetBuilder[MType]
+       redef fun build_poset(elements) do
+               var poset = new POSet[MType]
+               for e in elements do
+                       poset.add_node(e)
+                       for o in elements do
+                               if e == o then continue
+                               if e.is_subtype(mmodule, null, o) then
+                                       poset.add_edge(e, o)
+                               end
+                       end
+               end
+               return poset
+       end
+end
+
+# A TypingLayoutBuilder used for MClass based typing
+# such as in erased compilers or used in property coloring
+private class MClassPOSetBuilder
+       super POSetBuilder[MClass]
+       redef fun build_poset(elements) do return mmodule.flatten_mclass_hierarchy
+end
+
 # Matrice computers
 
 # Abstract layout builder for resolution tables using Binary Matrix (BM)
 abstract class TypingBMizer[E: Object]
        super TypingLayoutBuilder[E]
 
-       var mmodule: MModule
+       private var mmodule: MModule
+       private var poset_builder: POSetBuilder[E]
+       private var poset_cache: nullable POSet[E]
 
-       init(mmodule: MModule) do
+       private init(mmodule: MModule, poset_builder: POSetBuilder[E]) do
                self.mmodule = mmodule
+               self.poset_builder = poset_builder
        end
 
+       redef fun poset do return poset_cache
+
        # Compute mtypes ids and position using BM
        redef fun build_layout(elements: Set[E]): Layout[E] do
                var result = new Layout[E]
                var ids = new HashMap[E, Int]
-               var lin = self.reverse_linearize(elements)
+               poset_cache = poset_builder.build_poset(elements)
+               var lin = poset.to_a
+               poset.sort(lin)
                for element in lin do
                        ids[element] = ids.length
                end
@@ -94,30 +141,18 @@ abstract class TypingBMizer[E: Object]
                result.pos = ids
                return result
        end
-
-       private fun reverse_linearize(elements: Set[E]): Array[E] is abstract
 end
 
 # Layout builder for typing tables based on classes using Binary Matrix (BM)
 class MTypeBMizer
        super TypingBMizer[MType]
-
-       init(mmodule: MModule) do super(mmodule)
-
-       redef fun reverse_linearize(elements) do
-               return self.mmodule.reverse_linearize_mtypes(elements)
-       end
+       init(mmodule: MModule) do super(mmodule, new MTypePOSetBuilder(mmodule))
 end
 
 # Layout builder for typing tables based on types using Binary Matrix (BM)
 class MClassBMizer
        super TypingBMizer[MClass]
-
-       init(mmodule: MModule) do super(mmodule)
-
-       redef fun reverse_linearize(elements) do
-               return self.mmodule.reverse_linearize_mclasses(elements)
-       end
+       init(mmodule: MModule) do super(mmodule, new MClassPOSetBuilder(mmodule))
 end
 
 # Layout builder for resolution tables using Binary Matrix (BM)
@@ -156,7 +191,9 @@ abstract class MPropertyBMizer[E: MProperty]
        redef fun build_layout(elements) do
                var result = new Layout[E]
                var ids = new HashMap[E, Int]
-               var lin = linearize_mclasses(elements)
+               var lin = new Array[MClass]
+               lin.add_all(elements)
+               self.mmodule.linearize_mclasses(lin)
                for mclass in lin do
                        for mproperty in properties(mclass) do
                                if ids.has_key(mproperty) then continue
@@ -175,38 +212,27 @@ abstract class MPropertyBMizer[E: MProperty]
                end
                return properties
        end
-
-       private fun linearize_mclasses(mclasses: Set[MClass]): Array[MClass] is abstract
 end
 
 # Layout builder for vft using Binary Matrix (BM)
 class MMethodBMizer
        super MPropertyBMizer[MMethod]
-
        redef type MPROP: MMethod
        init(mmodule: MModule) do super(mmodule)
-       # Less holes in tables with reverse linearization for method tables
-       redef fun linearize_mclasses(mclasses) do return self.mmodule.reverse_linearize_mclasses(mclasses)
 end
 
 # Layout builder for attribute tables using Binary Matrix (BM)
 class MAttributeBMizer
        super MPropertyBMizer[MAttribute]
-
        redef type MPROP: MAttribute
        init(mmodule: MModule) do super(mmodule)
-       # Less holes in tables with linearization for attribute tables
-       redef fun linearize_mclasses(mclasses) do return self.mmodule.linearize_mclasses_2(mclasses)
 end
 
 # BMizing for MVirtualTypeProps
 class MVirtualTypePropBMizer
        super MPropertyBMizer[MVirtualTypeProp]
-
        redef type MPROP: MVirtualTypeProp
        init(mmodule: MModule) do super(mmodule)
-       # Less holes in tables with reverse linearization for method tables
-       redef fun linearize_mclasses(mclasses) do return self.mmodule.reverse_linearize_mclasses(mclasses)
 end
 
 # Colorers
@@ -218,13 +244,22 @@ abstract class TypingColorer[E: Object]
        private var core: Set[E] = new HashSet[E]
        private var crown: Set[E] = new HashSet[E]
        private var border: Set[E] = new HashSet[E]
-
        private var coloration_result: Map[E, Int] = new HashMap[E, Int]
 
-       init do end
+       private var mmodule: MModule
+       private var poset_builder: POSetBuilder[E]
+       private var poset_cache: nullable POSet[E]
+
+       private init(mmodule: MModule, poset_builder: POSetBuilder[E]) do
+               self.mmodule = mmodule
+               self.poset_builder = poset_builder
+       end
+
+       redef fun poset do return poset_cache
 
        # Compute the layout with coloring
        redef fun build_layout(elements: Set[E]): Layout[E] do
+               poset_cache = poset_builder.build_poset(elements)
                var result = new Layout[E]
                result.ids = compute_ids(elements)
                result.pos = colorize(elements)
@@ -233,8 +268,7 @@ abstract class TypingColorer[E: Object]
 
        private fun compute_ids(elements: Set[E]): Map[E, Int] do
                var ids = new HashMap[E, Int]
-               var lin = reverse_linearize(elements)
-               for element in lin do
+               for element in reverse_linearize(elements) do
                        ids[element] = ids.length
                end
                return ids
@@ -242,7 +276,7 @@ abstract class TypingColorer[E: Object]
 
        private fun colorize(elements: Set[E]): Map[E, Int] do
                tag_elements(elements)
-               build_conflicts_graph(elements)
+               build_conflicts_graph
                colorize_elements(core)
                colorize_elements(border)
                colorize_elements(crown)
@@ -271,7 +305,8 @@ abstract class TypingColorer[E: Object]
                                if coloration_result.has_key(st) and coloration_result[st] == color then return false
                        end
                end
-               for st in self.super_elements(element, elements) do
+               for st in self.poset[element].greaters do
+                       if st == element then continue
                        if coloration_result.has_key(st) and coloration_result[st] == color then return false
                end
                return true
@@ -282,23 +317,21 @@ abstract class TypingColorer[E: Object]
                for element in elements do
                        # Check if sub elements are all in single inheritance
                        var all_subelements_si = true
-                       for subelem in self.sub_elements(element, elements) do
-                               if self.is_element_mi(subelem, elements) then
+                       for subelem in self.poset[element].smallers do
+                               if self.poset[subelem].direct_greaters.length > 1 then
                                        all_subelements_si = false
                                        break
                                end
                        end
 
                        # Tag as core, crown or border
-                       if self.is_element_mi(element, elements) then
-                               core.add_all(self.super_elements(element, elements))
-                               core.add(element)
+                       if self.poset[element].direct_greaters.length > 1 then
+                               core.add_all(self.poset[element].greaters)
                                if all_subelements_si then
                                        border.add(element)
                                end
                        else if not all_subelements_si then
-                               core.add_all(self.super_elements(element, elements))
-                               core.add(element)
+                               core.add_all(self.poset[element].greaters)
                        else
                                crown.add(element)
                        end
@@ -306,18 +339,18 @@ abstract class TypingColorer[E: Object]
        end
 
        # Conflicts graph of elements hierarchy (two types are in conflict if they have common subelements)
-       private fun build_conflicts_graph(elements: Set[E]) do
+       private fun build_conflicts_graph do
                self.conflicts_graph = new HashMap[E, HashSet[E]]
                var core = reverse_linearize(self.core)
                for t in core do
-                       for i in self.linear_extension(t, elements) do
+                       for i in self.linear_extension(t) do
                                if t == i then continue
 
-                               var lin_i = self.linear_extension(i, elements)
+                               var lin_i = self.linear_extension(i)
 
-                               for j in self.linear_extension(t, elements) do
+                               for j in self.linear_extension(t) do
                                        if i == j or j == t then continue
-                                       var lin_j = self.linear_extension(j, elements)
+                                       var lin_j = self.linear_extension(j)
 
                                        var d_ij = lin_i - lin_j
                                        var d_ji = lin_j - lin_i
@@ -343,52 +376,34 @@ abstract class TypingColorer[E: Object]
        private var linear_extensions_cache: Map[E, Array[E]] = new HashMap[E, Array[E]]
 
        # Return a linear_extension of super_elements of the element
-       private fun linear_extension(element: E, elements: Set[E]): Array[E] do
+       private fun linear_extension(element: E): Array[E] do
                if not self.linear_extensions_cache.has_key(element) then
                        var supers = new HashSet[E]
-                       supers.add(element)
-                       supers.add_all(self.super_elements(element, elements))
+                       supers.add_all(self.poset[element].greaters)
                        self.linear_extensions_cache[element] = self.linearize(supers)
                end
                return self.linear_extensions_cache[element]
        end
 
-       private fun super_elements(element: E, elements: Set[E]): Set[E] is abstract
-       private fun sub_elements(element: E, elements: Set[E]): Set[E] is abstract
-       private fun is_element_mi(element: E, elements: Set[E]): Bool is abstract
-       private fun linearize(elements: Set[E]): Array[E] is abstract
-       private fun reverse_linearize(elements: Set[E]): Array[E] is abstract
+       private fun reverse_linearize(elements: Set[E]): Array[E] do
+               var lin = new Array[E]
+               lin.add_all(elements)
+               poset.sort(lin)
+               return lin
+       end
+       private fun linearize(elements: Set[E]): Array[E] do return reverse_linearize(elements).reversed
 end
 
 # Layout builder for typing tables based on types using coloration (CL)
 class MTypeColorer
        super TypingColorer[MType]
-
-       var mmodule: MModule
-
-       init(mmodule: MModule) do self.mmodule = mmodule
-
-       redef fun super_elements(element, elements) do return self.mmodule.super_mtypes(element, elements)
-       redef fun is_element_mi(element, elements) do return self.super_elements(element, elements).length > 1
-       redef fun sub_elements(element, elements) do do return self.mmodule.sub_mtypes(element, elements)
-       redef fun linearize(elements) do return self.mmodule.linearize_mtypes(elements)
-       redef fun reverse_linearize(elements) do return self.mmodule.reverse_linearize_mtypes(elements)
+       init(mmodule: MModule) do super(mmodule, new MTypePOSetBuilder(mmodule))
 end
 
 # Layout builder for typing tables based on classes using coloration (CL)
 class MClassColorer
        super TypingColorer[MClass]
-
-       private var mmodule: MModule
-
-       init(mmodule: MModule) do self.mmodule = mmodule
-
-       redef fun super_elements(element, elements) do return self.mmodule.super_mclasses(element)
-       fun parent_elements(element: MClass): Set[MClass] do return self.mmodule.parent_mclasses(element)
-       redef fun is_element_mi(element, elements) do return self.parent_elements(element).length > 1
-       redef fun sub_elements(element, elements) do do return self.mmodule.sub_mclasses(element)
-       redef fun linearize(elements) do return self.mmodule.linearize_mclasses_2(elements)
-       redef fun reverse_linearize(elements) do return self.mmodule.reverse_linearize_mclasses(elements)
+       init(mmodule: MModule) do super(mmodule, new MClassPOSetBuilder(mmodule))
 end
 
 # Abstract Layout builder for properties tables using coloration (CL)
@@ -401,9 +416,9 @@ abstract class MPropertyColorer[E: MProperty]
        private var class_colorer: MClassColorer
        private var coloration_result: Map[E, Int] = new HashMap[E, Int]
 
-       init(mmodule: MModule) do
+       init(mmodule: MModule, class_colorer: MClassColorer) do
                self.mmodule = mmodule
-               self.class_colorer = new MClassColorer(mmodule)
+               self.class_colorer = class_colorer
        end
 
        # Compute mclasses ids and position using BM
@@ -414,8 +429,6 @@ abstract class MPropertyColorer[E: MProperty]
        end
 
        private fun colorize(mclasses: Set[MClass]): Map[E, Int] do
-               self.class_colorer.tag_elements(mclasses)
-               self.class_colorer.build_conflicts_graph(mclasses)
                self.colorize_core(self.class_colorer.core)
                self.colorize_crown(self.class_colorer.crown)
                return self.coloration_result
@@ -426,26 +439,24 @@ abstract class MPropertyColorer[E: MProperty]
                var min_color = 0
                for mclass in mclasses do
                        var color = min_color
-
-                       # if the class is root, get the minimal color
-                       if self.mmodule.parent_mclasses(mclass).length == 0 then
-                               colorize_elements(self.properties(mclass), color)
-                       else
-                               # check last color used by parents
-                               color = max_color(color, self.mmodule.parent_mclasses(mclass))
-                               # check max color used in conflicts
-                               if self.class_colorer.conflicts_graph.has_key(mclass) then
-                                       color = max_color(color, self.class_colorer.conflicts_graph[mclass])
-                               end
-                               colorize_elements(self.properties(mclass), color)
+                       # check last color used by parents
+                       color = max_color(color, mclass.in_hierarchy(mmodule).direct_greaters)
+                       # check max color used in conflicts
+                       if self.class_colorer.conflicts_graph.has_key(mclass) then
+                               color = max_color(color, self.class_colorer.conflicts_graph[mclass])
                        end
+                       colorize_elements(self.properties(mclass), color)
                end
        end
 
        # Colorize properties of the crown hierarchy
        private fun colorize_crown(mclasses: Set[MClass]) do
                for mclass in mclasses do
-                       colorize_elements(self.properties(mclass), max_color(0, self.mmodule.parent_mclasses(mclass)))
+                       var parents = new HashSet[MClass]
+                       if mmodule.flatten_mclass_hierarchy.has(mclass) then
+                               parents.add_all(mclass.in_hierarchy(mmodule).direct_greaters)
+                       end
+                       colorize_elements(self.properties(mclass), max_color(0, parents))
                end
        end
 
@@ -488,7 +499,7 @@ class MMethodColorer
        super MPropertyColorer[MMethod]
 
        redef type MPROP: MMethod
-       init(mmodule: MModule) do super
+       init(mmodule: MModule, class_colorer: MClassColorer) do super(mmodule, class_colorer)
 end
 
 # Layout builder for attributes using coloration (CL)
@@ -496,7 +507,7 @@ class MAttributeColorer
        super MPropertyColorer[MAttribute]
 
        redef type MPROP: MAttribute
-       init(mmodule: MModule) do super
+       init(mmodule: MModule, class_colorer: MClassColorer) do super(mmodule, class_colorer)
 end
 
 # Layout builder for virtual types using coloration (CL)
@@ -504,7 +515,7 @@ class MVirtualTypePropColorer
        super MPropertyColorer[MVirtualTypeProp]
 
        redef type MPROP: MVirtualTypeProp
-       init(mmodule: MModule) do super
+       init(mmodule: MModule, class_colorer: MClassColorer) do super(mmodule, class_colorer)
 end
 
 # Layout builder for resolution tables using coloration (CL)
@@ -594,7 +605,7 @@ private class PerfectHasher[T: Object, U: Object]
 
        var operator: PHOperator
 
-       init(operator: PHOperator) do self.operator = operator
+       init do end
 
        # Compute mask for each holders
        fun compute_masks(conflicts: Map[T, Set[U]], ids: Map[U, Int]): Map[T, Int] do
@@ -665,26 +676,31 @@ class TypingHasher[E: Object]
        super PerfectHasher[E, E]
        super TypingLayoutBuilder[E]
 
-       var mmodule: MModule
+       private var mmodule: MModule
+       private var poset_builder: POSetBuilder[E]
+       private var poset_cache: nullable POSet[E]
 
-       init(operator: PHOperator, mmodule: MModule) do
-               super(operator)
+       private init(mmodule: MModule, poset_builder: POSetBuilder[E], operator: PHOperator) do
+               self.operator = operator
                self.mmodule = mmodule
+               self.poset_builder = poset_builder
        end
 
        redef fun build_layout(elements: Set[E]): PHLayout[E, E] do
+               poset_cache = poset_builder.build_poset(elements)
                var result = new PHLayout[E, E]
                var conflicts = self.build_conflicts(elements)
-               result.ids = self.compute_ids(elements)
+               result.ids = self.compute_ids
                result.masks = self.compute_masks(conflicts, result.ids)
                result.hashes = self.compute_hashes(conflicts, result.ids, result.masks)
                return result
        end
 
        # Ids start from 1 instead of 0
-       private fun compute_ids(elements: Set[E]): Map[E, Int] do
+       private fun compute_ids: Map[E, Int] do
                var ids = new HashMap[E, Int]
-               var lin = self.reverse_linearize(elements)
+               var lin = poset.to_a
+               poset.sort(lin)
                for e in lin do
                        ids[e] = ids.length + 1
                end
@@ -694,45 +710,25 @@ class TypingHasher[E: Object]
        private fun build_conflicts(elements: Set[E]): Map[E, Set[E]] do
                var conflicts = new HashMap[E, Set[E]]
                for e in elements do
-                       var supers = self.super_elements(e, elements)
+                       var supers = new HashSet[E]
+                       supers.add_all(self.poset[e].greaters)
                        supers.add(e)
                        conflicts[e] = supers
                end
                return conflicts
        end
-
-       private fun super_elements(element: E, elements: Set[E]): Set[E] is abstract
-       private fun reverse_linearize(elements: Set[E]): Array[E] is abstract
 end
 
 # Layout builder for typing tables with types using perfect hashing (PH)
 class MTypeHasher
        super TypingHasher[MType]
-
-       init(operator: PHOperator, mmodule: MModule) do super(operator, mmodule)
-
-       redef fun super_elements(element, elements) do
-               return self.mmodule.super_mtypes(element, elements)
-       end
-
-       redef fun reverse_linearize(elements) do
-               return self.mmodule.reverse_linearize_mtypes(elements)
-       end
+       init(operator: PHOperator, mmodule: MModule) do super(mmodule, new MTypePOSetBuilder(mmodule), operator)
 end
 
 # Layout builder for typing tables with classes using perfect hashing (PH)
 class MClassHasher
        super TypingHasher[MClass]
-
-       init(operator: PHOperator, mmodule: MModule) do super(operator, mmodule)
-
-       redef fun super_elements(element, elements) do
-               return self.mmodule.super_mclasses(element)
-       end
-
-       redef fun reverse_linearize(elements) do
-               return self.mmodule.reverse_linearize_mclasses(elements)
-       end
+       init(operator: PHOperator, mmodule: MModule) do super(mmodule, new MClassPOSetBuilder(mmodule), operator)
 end
 
 # Abstract layout builder for properties tables using perfect hashing (PH)
@@ -745,16 +741,30 @@ class MPropertyHasher[E: MProperty]
        var mmodule: MModule
 
        init(operator: PHOperator, mmodule: MModule) do
-               super(operator)
+               self.operator = operator
                self.mmodule = mmodule
        end
 
+       fun build_poset(mclasses: Set[MClass]): POSet[MClass] do
+               var poset = new POSet[MClass]
+               for e in mclasses do
+                       poset.add_node(e)
+                       for o in mclasses do
+                               if e == o or not mmodule.flatten_mclass_hierarchy.has(e) then continue
+                               if e.in_hierarchy(mmodule) < o then poset.add_edge(e, o)
+                       end
+               end
+               return poset
+       end
+
        redef fun build_layout(mclasses) do
                var result = new PHLayout[MClass, E]
                var ids = new HashMap[E, Int]
                var elements = new HashMap[MClass, Set[E]]
-               var lin = linearize_mclasses(mclasses)
-               for mclass in lin do
+               var poset = build_poset(mclasses)
+               var lin = poset.to_a
+               poset.sort(lin)
+               for mclass in lin.reversed do
                        var mproperties = properties(mclass)
                        for mproperty in mproperties do
                                if ids.has_key(mproperty) then continue
@@ -777,35 +787,27 @@ class MPropertyHasher[E: MProperty]
                end
                return properties
        end
-
-       private fun linearize_mclasses(mclasses: Set[MClass]): Array[MClass] is abstract
 end
 
 # Layout builder for vft using perfect hashing (PH)
 class MMethodHasher
        super MPropertyHasher[MMethod]
-
        redef type MPROP: MMethod
        init(operator: PHOperator, mmodule: MModule) do super(operator, mmodule)
-       redef fun linearize_mclasses(mclasses) do return self.mmodule.reverse_linearize_mclasses(mclasses)
 end
 
 # Layout builder for attributes tables using perfect hashing (PH)
 class MAttributeHasher
        super MPropertyHasher[MAttribute]
-
        redef type MPROP: MAttribute
        init(operator: PHOperator, mmodule: MModule) do super(operator, mmodule)
-       redef fun linearize_mclasses(mclasses) do return self.mmodule.linearize_mclasses_2(mclasses)
 end
 
 # Layout builder for virtual types tables using perfect hashing (PH)
 class MVirtualTypePropHasher
        super MPropertyHasher[MVirtualTypeProp]
-
        redef type MPROP: MVirtualTypeProp
        init(operator: PHOperator, mmodule: MModule) do super(operator, mmodule)
-       redef fun linearize_mclasses(mclasses) do return self.mmodule.reverse_linearize_mclasses(mclasses)
 end
 
 # Layout builder for resolution tables using perfect hashing (PH)
@@ -813,7 +815,7 @@ class ResolutionHasher
        super PerfectHasher[MClassType, MType]
        super ResolutionLayoutBuilder
 
-       init(operator: PHOperator) do super(operator)
+       init(operator: PHOperator) do self.operator = operator
 
        # Compute resolved types masks and hashes
        redef fun build_layout(elements) do
index 80d643f..1f4cb91 100644 (file)
@@ -140,6 +140,7 @@ redef class MModule
                for m in self.in_importation.greaters do
                        for cd in m.mclassdefs do
                                var c = cd.mclass
+                               res.add_node(c)
                                for s in cd.supertypes do
                                        res.add_edge(c, s.mclass)
                                end
index a2e5128..d08e03f 100644 (file)
@@ -233,8 +233,11 @@ class SeparateCompiler
                #       method_layout_builder = new MMethodHasher(new PHAndOperator, self.mainmodule)
                #       attribute_layout_builder = new MAttributeHasher(new PHAndOperator, self.mainmodule)
                #else
-               method_layout_builder = new MMethodColorer(self.mainmodule)
-               attribute_layout_builder = new MAttributeColorer(self.mainmodule)
+
+               var class_layout_builder = new MClassColorer(self.mainmodule)
+               class_layout_builder.build_layout(mclasses)
+               method_layout_builder = new MMethodColorer(self.mainmodule, class_layout_builder)
+               attribute_layout_builder = new MAttributeColorer(self.mainmodule, class_layout_builder)
                #end
 
                # methods coloration
@@ -255,9 +258,13 @@ class SeparateCompiler
                for mclass in mclasses do
                        var table = new Array[nullable MPropDef]
                        # first, fill table from parents by reverse linearization order
-                       var parents = self.mainmodule.super_mclasses(mclass)
-                       var lin = self.mainmodule.reverse_linearize_mclasses(parents)
-                       for parent in lin do
+                       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
                                        if not mproperty isa MMethod then continue
                                        var color = layout.pos[mproperty]
@@ -299,9 +306,13 @@ class SeparateCompiler
                for mclass in mclasses do
                        var table = new Array[nullable MPropDef]
                        # first, fill table from parents by reverse linearization order
-                       var parents = self.mainmodule.super_mclasses(mclass)
-                       var lin = self.mainmodule.reverse_linearize_mclasses(parents)
-                       for parent in lin do
+                       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
                                        if not mproperty isa MAttribute then continue
                                        var color = layout.pos[mproperty]
@@ -339,7 +350,7 @@ class SeparateCompiler
        end
 
        # colorize live types of the program
-       private fun do_type_coloring: Set[MType] do
+       private fun do_type_coloring: POSet[MType] do
                var mtypes = new HashSet[MType]
                mtypes.add_all(self.runtime_type_analysis.live_types)
                mtypes.add_all(self.runtime_type_analysis.live_cast_types)
@@ -367,24 +378,22 @@ class SeparateCompiler
 
                # colorize types
                self.type_layout = layout_builder.build_layout(mtypes)
-               self.type_tables = self.build_type_tables(mtypes)
+               var poset = layout_builder.poset.as(not null)
+               self.type_tables = self.build_type_tables(poset)
 
                # VT and FT are stored with other unresolved types in the big resolution_tables
                self.compile_resolution_tables(mtypes)
 
-               return mtypes
+               return poset
        end
 
        # Build type tables
-       fun build_type_tables(mtypes: Set[MType]): Map[MType, Array[nullable MType]] do
+       fun build_type_tables(mtypes: POSet[MType]): Map[MType, Array[nullable MType]] do
                var tables = new HashMap[MType, Array[nullable MType]]
                var layout = self.type_layout
                for mtype in mtypes do
                        var table = new Array[nullable MType]
-                       var supers = new HashSet[MType]
-                       supers.add_all(self.mainmodule.super_mtypes(mtype, mtypes))
-                       supers.add(mtype)
-                       for sup in supers do
+                       for sup in mtypes[mtype].greaters do
                                var color: Int
                                if layout isa PHLayout[MType, MType] then
                                        color = layout.hashes[mtype][sup]
index 2b3d304..5758950 100644 (file)
@@ -82,20 +82,24 @@ class SeparateErasureCompiler
                var mclasses = new HashSet[MClass].from(mmbuilder.model.mclasses)
 
                var layout_builder: TypingLayoutBuilder[MClass]
+               var class_colorer = new MClassColorer(mainmodule)
                if modelbuilder.toolcontext.opt_phmod_typing.value then
                        layout_builder = new MClassHasher(new PHModOperator, mainmodule)
+                       class_colorer.build_layout(mclasses)
                else if modelbuilder.toolcontext.opt_phand_typing.value then
                        layout_builder = new MClassHasher(new PHAndOperator, mainmodule)
+                       class_colorer.build_layout(mclasses)
                else if modelbuilder.toolcontext.opt_bm_typing.value then
                        layout_builder = new MClassBMizer(mainmodule)
+                       class_colorer.build_layout(mclasses)
                else
-                       layout_builder = new MClassColorer(mainmodule)
+                       layout_builder = class_colorer
                end
                self.class_layout = layout_builder.build_layout(mclasses)
                self.class_tables = self.build_class_typing_tables(mclasses)
 
                # vt coloration
-               var vt_coloring = new MVirtualTypePropColorer(mainmodule)
+               var vt_coloring = new MVirtualTypePropColorer(mainmodule, class_colorer)
                var vt_layout = vt_coloring.build_layout(mclasses)
                self.vt_tables = build_vt_tables(mclasses, vt_layout)
                self.vt_layout = vt_layout
@@ -106,9 +110,13 @@ class SeparateErasureCompiler
                for mclass in mclasses do
                        var table = new Array[nullable MPropDef]
                        # first, fill table from parents by reverse linearization order
-                       var parents = self.mainmodule.super_mclasses(mclass)
-                       var lin = self.mainmodule.reverse_linearize_mclasses(parents)
-                       for parent in lin do
+                       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
                                        if not mproperty isa MVirtualTypeProp then continue
                                        var color = layout.pos[mproperty]
@@ -151,9 +159,10 @@ class SeparateErasureCompiler
                var layout = self.class_layout
                for mclass in mclasses do
                        var table = new Array[nullable MClass]
-                       var supers = new HashSet[MClass]
-                       supers.add_all(self.mainmodule.super_mclasses(mclass))
-                       supers.add(mclass)
+                       var supers = new Array[MClass]
+                       if mainmodule.flatten_mclass_hierarchy.has(mclass) then
+                               supers = mclass.in_hierarchy(mainmodule).greaters.to_a
+                       end
                        for sup in supers do
                                var color: Int
                                if layout isa PHLayout[MClass, MClass] then