nitg-s: replaced TypePerfectHashing by PHTypeLayoutBuilder
authorAlexandre Terrasa <alexandre@moz-code.org>
Thu, 7 Feb 2013 18:18:14 +0000 (13:18 -0500)
committerAlexandre Terrasa <alexandre@moz-code.org>
Mon, 4 Mar 2013 18:20:00 +0000 (13:20 -0500)
Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

src/coloring.nit
src/separate_compiler.nit

index 765533e..ea5715c 100644 (file)
@@ -17,12 +17,32 @@ module coloring
 
 import typing
 
+# Layouts
+
+class TypeLayout
+       # Unic ids or each Mtype
+       var ids: Map[MType, Int] = new HashMap[MType, Int]
+       # Fixed positions of each MType in all tables
+       var pos: Map[MType, Int] = new HashMap[MType, Int]
+end
+
+class PHTypeLayout
+       super TypeLayout
+       # Masks used by hash function
+       var masks: Map[MType, Int] = new HashMap[MType, Int]
+       # Positions of each MType for each tables
+       var hashes: Map[MType, Map[MType, Int]] = new HashMap[MType, Map[MType, Int]]
+end
+
 abstract class TypeLayoutBuilder
+
+       type LAYOUT: TypeLayout
+
        private var mmodule: MModule
        init(mmodule: MModule) do self.mmodule = mmodule
 
        # Compute mtypes ids and position
-       fun build_layout(mtypes: Set[MType]): TypeLayout is abstract
+       fun build_layout(mtypes: Set[MType]): LAYOUT is abstract
 
        # Give each MType a unic id using a descending linearization of the `mtypes` set
        private fun compute_ids(mtypes: Set[MType]): Map[MType, Int] do
@@ -35,13 +55,6 @@ abstract class TypeLayoutBuilder
        end
 end
 
-class TypeLayout
-       # Unic ids or each Mtype
-       var ids: Map[MType, Int] = new HashMap[MType, Int]
-       # Fixed positions of each MType in all tables
-       var pos: Map[MType, Int] = new HashMap[MType, Int]
-end
-
 # Layout builder for MType using Binary Matrix (BM)
 class BMTypeLayoutBuilder
        super TypeLayoutBuilder
@@ -69,7 +82,7 @@ class CLTypeLayoutBuilder
        end
 
        # Compute mtypes ids and position using BM
-       redef fun build_layout(mtypes: Set[MType]): TypeLayout do
+       redef fun build_layout(mtypes) do
                var result = new TypeLayout
                result.ids = self.compute_ids(mtypes)
                result.pos = self.colorer.colorize(mtypes)
@@ -77,6 +90,39 @@ class CLTypeLayoutBuilder
        end
 end
 
+# Layout builder for MType using Perfect Hashing (PH)
+class PHTypeLayoutBuilder
+       super TypeLayoutBuilder
+
+       redef type LAYOUT: PHTypeLayout
+
+       private var hasher: MTypeHasher
+
+       init(mmodule: MModule, operator: PHOperator) do
+               super
+               self.hasher = new MTypeHasher(mmodule, operator)
+       end
+
+       # Compute mtypes ids and position using BM
+       redef fun build_layout(mtypes) do
+               var result = new PHTypeLayout
+               result.ids = self.compute_ids(mtypes)
+               result.masks = self.hasher.compute_masks(mtypes, result.ids)
+               result.hashes = self.hasher.compute_hashes(mtypes, result.ids, result.masks)
+               return result
+       end
+
+       # Ids start from 1 instead of 0
+       redef fun compute_ids(mtypes) do
+               var ids = new HashMap[MType, Int]
+               var lin = self.mmodule.reverse_linearize_mtypes(mtypes)
+               for mtype in lin do
+                       ids[mtype] = ids.length + 1
+               end
+               return ids
+       end
+end
+
 abstract class AbstractColoring[E: Object]
 
        private var core: Set[E] = new HashSet[E]
@@ -224,63 +270,81 @@ private class MTypeColorer
        redef fun reverse_linearize(elements) do return self.mmodule.reverse_linearize_mtypes(elements)
 end
 
-abstract class TypePerfectHashing
-       super TypeLayoutBuilder
-       super AbstractColoring[MType]
+# MType Perfect Hashing
+private class MTypeHasher
 
-       type T: MType
+       var mmodule: MModule
+       var operator: PHOperator
 
-       init(mmodule: MModule) do self.mmodule = mmodule
+       init(mmodule: MModule, operator: PHOperator) do
+               self.mmodule = mmodule
+               self.operator = operator
+       end
 
-       fun compute_masks(elements: Set[T], ids: Map[T, Int]): Map[T, Int] do
-               for e in elements do
-                       # Create super type list
-                       var supers = new HashSet[T]
-                       supers.add_all(self.super_elements(e, elements))
-                       supers.add(e)
-                       # Compute the hashing 'mask'
-                       self.coloration_result[e] = compute_mask(supers, ids)
+       fun compute_masks(mtypes: Set[MType], ids: Map[MType, Int]): Map[MType, Int] do
+               var masks = new HashMap[MType, Int]
+               for mtype in mtypes do
+                       var supers = new HashSet[MType]
+                       supers.add_all(self.mmodule.super_mtypes(mtype, mtypes))
+                       supers.add(mtype)
+                       masks[mtype] = compute_mask(supers, ids)
                end
-               return self.coloration_result
+               return masks
        end
 
-       private fun compute_mask(mtypes: Set[T], ids: Map[T, Int]): Int do
+       private fun compute_mask(supers: Set[MType], ids: Map[MType, Int]): Int do
                var mask = 0
                loop
                        var used = new List[Int]
-                       for sup in mtypes do
-                               var res = op(mask, ids[sup])
+                       for sup in supers do
+                               var res = operator.op(mask, ids[sup])
                                if used.has(res) then
                                        break
                                else
                                        used.add(res)
                                end
                        end
-                       if used.length == mtypes.length then break
+                       if used.length == supers.length then break
                        mask += 1
                end
                return mask
        end
 
-       private fun op(mask: Int, id:Int): Int is abstract
-       private fun phash(id: Int, mask: Int): Int do return op(mask, id)
+       fun compute_hashes(mtypes: Set[MType], ids: Map[MType, Int], masks: Map[MType, Int]): Map[MType, Map[MType, Int]] do
+               var hashes = new HashMap[MType, Map[MType, Int]]
+               for mtype in mtypes do
+                       var supers = new HashSet[MType]
+                       supers.add_all(self.mmodule.super_mtypes(mtype, mtypes))
+                       supers.add(mtype)
+                       var inhashes = new HashMap[MType, Int]
+                       var mask = masks[mtype]
+                       for sup in supers do
+                               inhashes[sup] = operator.op(mask, ids[sup])
+                       end
+                       hashes[mtype] = inhashes
+               end
+               return hashes
+       end
+end
 
-       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)
+# Abstract operator used for perfect hashing
+abstract class PHOperator
+       fun op(mask: Int, id:Int): Int is abstract
 end
 
-class TypeModPerfectHashing
-       super TypePerfectHashing
-       init(mainmodule: MModule) do super
+# Hashing using modulo (MOD) operator
+# slower but compact
+class PHModOperator
+       super PHOperator
+       init do end
        redef fun op(mask, id) do return mask % id
 end
 
-class TypeAndPerfectHashing
-       super TypePerfectHashing
-       init(mainmodule: MModule) do super
+# Hashing using binary and (AND) operator
+# faster but sparse
+class PHAndOperator
+       super PHOperator
+       init do end
        redef fun op(mask, id) do return mask.bin_and(id)
 end
 
index 7029a43..816b1fd 100644 (file)
@@ -136,8 +136,8 @@ class SeparateCompiler
 
        init(mainmodule: MModule, mmbuilder: ModelBuilder, runtime_type_analysis: RapidTypeAnalysis) do
                super
-               self.init_layout_builders
                self.header = new_visitor
+               self.init_layout_builders
                self.runtime_type_analysis = runtime_type_analysis
                self.do_property_coloring
                self.compile_box_kinds
@@ -148,9 +148,11 @@ class SeparateCompiler
                if modelbuilder.toolcontext.opt_bm_typing.value then
                        self.type_layout_builder = new BMTypeLayoutBuilder(self.mainmodule)
                else if modelbuilder.toolcontext.opt_phmod_typing.value then
-                       self.type_layout_builder = new TypeModPerfectHashing(self.mainmodule)
+                       self.type_layout_builder = new PHTypeLayoutBuilder(self.mainmodule, new PHModOperator)
+                       self.header.add_decl("#define HASH(mask, id) ((mask)%(id))")
                else if modelbuilder.toolcontext.opt_phand_typing.value then
-                       self.type_layout_builder = new TypeAndPerfectHashing(self.mainmodule)
+                       self.type_layout_builder = new PHTypeLayoutBuilder(self.mainmodule, new PHAndOperator)
+                       self.header.add_decl("#define HASH(mask, id) ((mask)&(id))")
                else
                        self.type_layout_builder = new CLTypeLayoutBuilder(self.mainmodule)
                end
@@ -297,41 +299,22 @@ class SeparateCompiler
                end
                mtypes.add_all(self.partial_types)
 
-               # set type unique id
-               if modelbuilder.toolcontext.opt_phmod_typing.value or modelbuilder.toolcontext.opt_phand_typing.value then
-                       var sorted_mtypes = new Array[MType].from(mtypes)
-                       var sorter = new ReverseTypeSorter(self.mainmodule)
-                       sorter.sort(sorted_mtypes)
-                       for mtype in sorted_mtypes do
-                               self.typeids[mtype] = self.typeids.length + 1
-                       end
-               else
-                       for mtype in mtypes do
-                               self.typeids[mtype] = self.typeids.length
-                       end
-               end
-
                # VT and FT are stored with other unresolved types in the big unanchored_tables
                self.compile_unanchored_tables(mtypes)
 
                # colorize types
                var type_coloring = self.type_layout_builder
-               if type_coloring isa TypeModPerfectHashing then
-                       self.type_colors = type_coloring.compute_masks(mtypes, typeids)
-                       self.type_tables = self.hash_type_tables(mtypes, typeids, type_colors, type_coloring)
-                       self.header.add_decl("#define HASH(mask, id) ((mask)%(id))")
-               else if type_coloring isa TypeAndPerfectHashing then
-                       self.type_colors = type_coloring.compute_masks(mtypes, typeids)
-                       self.type_tables = self.hash_type_tables(mtypes, typeids, type_colors, type_coloring)
-                       self.header.add_decl("#define HASH(mask, id) ((mask)&(id))")
+               if type_coloring isa PHTypeLayoutBuilder then
+                       var result = type_coloring.build_layout(mtypes)
+                       self.typeids = result.ids
+                       self.type_colors = result.masks
+                       self.type_tables = self.hash_type_tables(mtypes, result.hashes)
                else
                        var result = type_coloring.build_layout(mtypes)
                        self.typeids = result.ids
                        self.type_colors = result.pos
                        self.type_tables = self.build_type_tables(mtypes, type_colors, type_coloring)
                end
-
-
                return mtypes
        end
 
@@ -359,17 +342,13 @@ class SeparateCompiler
        end
 
        # Build type tables
-       fun hash_type_tables(mtypes: Set[MType], ids: Map[MType, Int], masks: Map[MType, Int], colorer: TypePerfectHashing): Map[MType, Array[nullable MType]] do
+       fun hash_type_tables(mtypes: Set[MType], hashes: Map[MType, Map[MType, Int]]): Map[MType, Array[nullable MType]] do
                var tables = new HashMap[MType, Array[nullable MType]]
 
                for mtype in mtypes do
                        var table = new Array[nullable MType]
-                       var supers = new HashSet[MType]
-                       supers.add_all(colorer.super_elements(mtype, mtypes))
-                       supers.add(mtype)
-
-                       for sup in supers do
-                               var color = colorer.phash(ids[sup], masks[mtype])
+                       var supers = hashes[mtype]
+                       for sup, color in supers do
                                if table.length <= color then
                                        for i in [table.length .. color[ do
                                                table[i] = null