bench: replace shootout_binarytrees with bench_bintree_gen
[nit.git] / src / separate_compiler.nit
index 84f6682..61e22ec 100644 (file)
@@ -17,7 +17,8 @@ module separate_compiler
 
 
 import global_compiler # TODO better separation of concerns
 
 
 import global_compiler # TODO better separation of concerns
-intrude import coloring
+import coloring
+
 redef class ToolContext
        # --separate
        var opt_separate: OptionBool = new OptionBool("Use separate compilation", "--separate")
 redef class ToolContext
        # --separate
        var opt_separate: OptionBool = new OptionBool("Use separate compilation", "--separate")
@@ -25,11 +26,31 @@ redef class ToolContext
        # --no-inline-intern
        var opt_no_inline_intern: OptionBool = new OptionBool("Do not inline call to intern methods", "--no-inline-intern")
 
        # --no-inline-intern
        var opt_no_inline_intern: OptionBool = new OptionBool("Do not inline call to intern methods", "--no-inline-intern")
 
+       # --inline-coloring-numbers
+       var opt_inline_coloring_numbers: OptionBool = new OptionBool("Inline colors and ids", "--inline-coloring-numbers")
+
+       # --use-naive-coloring
+       var opt_bm_typing: OptionBool = new OptionBool("Colorize items incrementaly, used to simulate binary matrix typing", "--bm-typing")
+
+       # --use-mod-perfect-hashing
+       var opt_phmod_typing: OptionBool = new OptionBool("Replace coloration by perfect hashing (with mod operator)", "--phmod-typing")
+
+       # --use-and-perfect-hashing
+       var opt_phand_typing: OptionBool = new OptionBool("Replace coloration by perfect hashing (with and operator)", "--phand-typing")
+
+       # --generic-resolution-tree
+       var opt_generic_tree: OptionBool = new OptionBool("Use tree representation for live generic types instead of flattened representation", "--generic-resolution-tree")
+
        redef init
        do
                super
                self.option_context.add_option(self.opt_separate)
                self.option_context.add_option(self.opt_no_inline_intern)
        redef init
        do
                super
                self.option_context.add_option(self.opt_separate)
                self.option_context.add_option(self.opt_no_inline_intern)
+               self.option_context.add_option(self.opt_inline_coloring_numbers)
+               self.option_context.add_option(self.opt_bm_typing)
+               self.option_context.add_option(self.opt_phmod_typing)
+               self.option_context.add_option(self.opt_phand_typing)
+               self.option_context.add_option(self.opt_generic_tree)
        end
 end
 
        end
 end
 
@@ -40,33 +61,6 @@ redef class ModelBuilder
                self.toolcontext.info("*** COMPILING TO C ***", 1)
 
                var compiler = new SeparateCompiler(mainmodule, runtime_type_analysis, self)
                self.toolcontext.info("*** COMPILING TO C ***", 1)
 
                var compiler = new SeparateCompiler(mainmodule, runtime_type_analysis, self)
-               var v = compiler.new_visitor
-               compiler.header = v
-               v.add_decl("#include <stdlib.h>")
-               v.add_decl("#include <stdio.h>")
-               v.add_decl("#include <string.h>")
-               v.add_decl("#include <gc/gc.h>")
-               v.add_decl("typedef void(*nitmethod_t)(void); /* general C type representing a Nit method. */")
-               v.add_decl("typedef void* nitattribute_t; /* general C type representing a Nit attribute. */")
-
-               # Class abstract representation
-               v.add_decl("struct class \{ int box_kind; nitmethod_t vft[1]; \}; /* general C type representing a Nit class. */")
-               # Type abstract representation
-               v.add_decl("struct type \{ int id; int color; int livecolor; short int is_nullable; struct vts_table *vts_table; struct fts_table *fts_table; int table_size; int type_table[1]; \}; /* general C type representing a Nit type. */")
-               v.add_decl("struct fts_table \{ struct type *fts[1]; \}; /* fts list of a C type representation. */")
-               v.add_decl("struct vts_table \{ struct type *vts[1]; \}; /* vts list of a C type representation. */")
-               # Instance abstract representation
-               v.add_decl("typedef struct \{ struct type *type; struct class *class; nitattribute_t attrs[1]; \} val; /* general C type representing a Nit instance. */")
-
-               compiler.compile_box_kinds
-
-               # Declare global instances
-               v.add_decl("extern int glob_argc;")
-               v.add_decl("extern char **glob_argv;")
-               v.add_decl("extern val *glob_sys;")
-
-               # The main function of the C
-               compiler.compile_main_function
 
                # compile class structures
                for m in mainmodule.in_importation.greaters do
 
                # compile class structures
                for m in mainmodule.in_importation.greaters do
@@ -75,25 +69,27 @@ redef class ModelBuilder
                        end
                end
 
                        end
                end
 
+               # The main function of the C
+               compiler.compile_main_function
+
                # compile methods
                for m in mainmodule.in_importation.greaters do
                        compiler.compile_module_to_c(m)
                end
 
                # compile live & cast type structures
                # compile methods
                for m in mainmodule.in_importation.greaters do
                        compiler.compile_module_to_c(m)
                end
 
                # compile live & cast type structures
-               var mtypes = compiler.do_global_type_coloring
+               var mtypes = compiler.do_type_coloring
                for t in mtypes do
                        compiler.compile_type_to_c(t)
                end
 
                for t in mtypes do
                        compiler.compile_type_to_c(t)
                end
 
-               # compile live generic types selection structures
-               for mclass in model.mclasses do
-                       compiler.compile_live_gentype_to_c(mclass)
+               if self.toolcontext.opt_generic_tree.value then
+                       # compile live generic types selection structures
+                       for mclass in model.mclasses do
+                               compiler.compile_live_gentype_to_c(mclass)
+                       end
                end
 
                end
 
-               # for the class_name and output_class_name methods
-               compiler.compile_class_names
-
                write_and_make(compiler)
        end
 end
                write_and_make(compiler)
        end
 end
@@ -103,6 +99,7 @@ class SeparateCompiler
        super GlobalCompiler # TODO better separation of concerns
 
        private var undead_types: Set[MType] = new HashSet[MType]
        super GlobalCompiler # TODO better separation of concerns
 
        private var undead_types: Set[MType] = new HashSet[MType]
+       private var partial_types: Set[MType] = new HashSet[MType]
        protected var typeids: HashMap[MType, Int] protected writable = new HashMap[MType, Int]
 
        private var type_colors: Map[MType, Int] = typeids
        protected var typeids: HashMap[MType, Int] protected writable = new HashMap[MType, Int]
 
        private var type_colors: Map[MType, Int] = typeids
@@ -111,45 +108,56 @@ class SeparateCompiler
        private var livetypes_colors: nullable Map[MType, Int]
        private var livetypes_tables: nullable Map[MClass, Array[nullable Object]]
        private var livetypes_tables_sizes: nullable Map[MClass, Array[Int]]
        private var livetypes_colors: nullable Map[MType, Int]
        private var livetypes_tables: nullable Map[MClass, Array[nullable Object]]
        private var livetypes_tables_sizes: nullable Map[MClass, Array[Int]]
+       private var live_unanchored_types: Map[MClassDef, Set[MType]] = new HashMap[MClassDef, HashSet[MType]]
 
 
-       protected var class_colors: Map[MClass, Int] protected writable
+       private var unanchored_types_colors: nullable Map[MClassType, Int]
+       private var unanchored_types_tables: nullable Map[MClassType, Array[nullable MClassType]]
+       private var unanchored_types_masks: nullable Map[MClassType, Int]
 
 
-       protected var method_colors: Map[MMethod, Int] protected writable
-       protected var method_tables: Map[MClass, Array[nullable MMethodDef]] protected writable
+       protected var class_coloring: ClassColoring
 
 
-       protected var attr_colors: Map[MAttribute, Int] protected writable
-       protected var attr_tables: Map[MClass, Array[nullable MAttributeDef]] protected writable
+       protected var method_colors: Map[MMethod, Int]
+       protected var method_tables: Map[MClass, Array[nullable MMethodDef]]
 
 
-       private var vt_colors: Map[MVirtualTypeProp, Int]
-       private var vt_tables: Map[MClass, Array[nullable MVirtualTypeDef]]
+       protected var attr_colors: Map[MAttribute, Int]
+       protected var attr_tables: Map[MClass, Array[nullable MAttributeDef]]
 
 
-       private var ft_colors: Map[MParameterType, Int]
-       private var ft_tables: Map[MClass, Array[nullable MParameterType]]
+       protected var vt_colors: Map[MVirtualTypeProp, Int]
+       protected var vt_tables: Map[MClass, Array[nullable MVirtualTypeDef]]
+       protected var vt_masks: nullable Map[MClass, Int]
+
+       private var ft_colors: nullable Map[MParameterType, Int]
+       private var ft_tables: nullable Map[MClass, Array[nullable MParameterType]]
+       private var ft_masks: nullable Map[MClass, Int]
 
        init(mainmodule: MModule, runtime_type_analysis: RapidTypeAnalysis, mmbuilder: ModelBuilder) do
 
        init(mainmodule: MModule, runtime_type_analysis: RapidTypeAnalysis, mmbuilder: ModelBuilder) do
-               # classes coloration
-               var class_coloring = new ClassColoring(mainmodule)
-               self.class_colors = class_coloring.colorize(mmbuilder.model.mclasses)
+               self.do_property_coloring
+               self.compile_box_kinds
+       end
 
 
-               # methods coloration
-               var method_coloring = new MethodColoring(class_coloring)
-               self.method_colors = method_coloring.colorize
-               self.method_tables = method_coloring.build_property_tables
+       redef fun compile_header_structs do
+               self.header.add_decl("typedef void(*nitmethod_t)(void); /* general C type representing a Nit method. */")
+               self.header.add_decl("typedef void* nitattribute_t; /* general C type representing a Nit attribute. */")
+               self.header.add_decl("struct class \{ int box_kind; nitmethod_t vft[1]; \}; /* general C type representing a Nit class. */")
 
 
-               # attributes coloration
-               var attribute_coloring = new AttributeColoring(class_coloring)
-               self.attr_colors = attribute_coloring.colorize
-               self.attr_tables = attribute_coloring.build_property_tables
+               if modelbuilder.toolcontext.opt_generic_tree.value then
+                       self.header.add_decl("struct type \{ int id; const char *name; int color; short int is_nullable; int livecolor; struct types *vts_table; struct types *fts_table; int table_size; int type_table[1]; \}; /* general C type representing a Nit type. */")
+               else
+                       self.header.add_decl("struct type \{ int id; const char *name; int color; short int is_nullable; struct types *unanchored_table; struct types *vts_table; struct types *fts_table; int table_size; int type_table[1]; \}; /* general C type representing a Nit type. */")
+               end
 
 
-               # vt coloration
-               var vt_coloring = new VTColoring(class_coloring)
-               self.vt_colors = vt_coloring.colorize
-               self.vt_tables = vt_coloring.build_property_tables
-
-               # fts coloration
-               var ft_coloring = new FTColoring(class_coloring)
-               self.ft_colors = ft_coloring.colorize
-               self.ft_tables = ft_coloring.build_ft_tables
+               if modelbuilder.toolcontext.opt_phmod_typing.value or modelbuilder.toolcontext.opt_phand_typing.value then
+                       self.header.add_decl("struct types \{ int mask; struct type *types[1]; \}; /* a list types (used for vts, fts and unanchored lists). */")
+               else
+                       self.header.add_decl("struct types \{ struct type *types[1]; \}; /* a list types (used for vts, fts and unanchored lists). */")
+               end
+
+
+               self.header.add_decl("typedef struct \{ struct type *type; struct class *class; nitattribute_t attrs[1]; \} val; /* general C type representing a Nit instance. */")
+       end
+
+       redef fun compile_class_names do
+               abort # There is no class name compilation since the name is stored in the type structure
        end
 
        fun compile_box_kinds
        end
 
        fun compile_box_kinds
@@ -178,82 +186,250 @@ class SeparateCompiler
 
        end
 
 
        end
 
-       protected fun compile_class_names do
-
-               # Build type names table
-               var type_array = new Array[nullable MType]
-               for t, i in typeids do
-                       if i >= type_array.length then
-                               type_array[i] = null
+       fun compile_color_consts(colors: Map[Object, Int]) do
+               for m, c in colors do
+                       if m isa MProperty then
+                               if modelbuilder.toolcontext.opt_inline_coloring_numbers.value then
+                                       self.header.add_decl("#define {m.const_color} {c}")
+                               else
+                                       self.header.add_decl("extern const int {m.const_color};")
+                                       self.header.add("const int {m.const_color} = {c};")
+                               end
+                       else if m isa MType then
+                               if modelbuilder.toolcontext.opt_inline_coloring_numbers.value then
+                                       self.header.add_decl("#define {m.const_color} {c}")
+                               else
+                                       self.header.add_decl("extern const int {m.const_color};")
+                                       self.header.add("const int {m.const_color} = {c};")
+                               end
                        end
                        end
-                       type_array[i] = t
                end
                end
+       end
 
 
-               var v = self.new_visitor
-               self.header.add_decl("extern const char const * class_names[];")
-               v.add("const char const * class_names[] = \{")
-               for t in type_array do
-                       if t == null then
-                               v.add("NULL,")
-                       else
-                               v.add("\"{t}\",")
-                       end
+       # colorize classe properties
+       fun do_property_coloring do
+
+               # classes coloration
+               self.class_coloring = new ClassColoring(mainmodule)
+               class_coloring.colorize(modelbuilder.model.mclasses)
+
+               # methods coloration
+               var method_coloring = new MethodColoring(self.class_coloring)
+               self.method_colors = method_coloring.colorize
+               self.method_tables = method_coloring.build_property_tables
+               self.compile_color_consts(self.method_colors)
+
+               # attributes coloration
+               var attribute_coloring = new AttributeColoring(self.class_coloring)
+               self.attr_colors = attribute_coloring.colorize
+               self.attr_tables = attribute_coloring.build_property_tables
+               self.compile_color_consts(self.attr_colors)
+
+               if modelbuilder.toolcontext.opt_bm_typing.value then
+                       self.class_coloring = new NaiveClassColoring(mainmodule)
+                       self.class_coloring.colorize(modelbuilder.model.mclasses)
                end
                end
-               v.add("\};")
+
+               # vt coloration
+               if modelbuilder.toolcontext.opt_bm_typing.value then
+                       var vt_coloring = new NaiveVTColoring(self.class_coloring)
+                       self.vt_colors = vt_coloring.colorize
+                       self.vt_tables = vt_coloring.build_property_tables
+               else if modelbuilder.toolcontext.opt_phmod_typing.value then
+                       var vt_coloring = new VTModPerfectHashing(self.class_coloring)
+                       self.vt_colors = vt_coloring.colorize
+                       self.vt_masks = vt_coloring.compute_masks
+                       self.vt_tables = vt_coloring.build_property_tables
+               else if modelbuilder.toolcontext.opt_phand_typing.value then
+                       var vt_coloring = new VTAndPerfectHashing(self.class_coloring)
+                       self.vt_colors = vt_coloring.colorize
+                       self.vt_masks = vt_coloring.compute_masks
+                       self.vt_tables = vt_coloring.build_property_tables
+               else
+                       var vt_coloring = new VTColoring(self.class_coloring)
+                       self.vt_colors = vt_coloring.colorize
+                       self.vt_tables = vt_coloring.build_property_tables
+               end
+               self.compile_color_consts(self.vt_colors)
        end
 
        # colorize live types of the program
        end
 
        # colorize live types of the program
-       private fun do_global_type_coloring: Set[MType] do
+       private fun do_type_coloring: Set[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)
                mtypes.add_all(self.undead_types)
 
                var mtypes = new HashSet[MType]
                mtypes.add_all(self.runtime_type_analysis.live_types)
                mtypes.add_all(self.runtime_type_analysis.live_cast_types)
                mtypes.add_all(self.undead_types)
 
-               self.undead_types.clear
                for mtype in mtypes do
                for mtype in mtypes do
-                       # add formal types arguments to mtypes
-                       if mtype isa MGenericType then
-                               for ft in mtype.arguments do
-                                       if ft.need_anchor then
-                                               print("Why do we need anchor here ?")
-                                               abort
-                                       end
-                                       self.undead_types.add(ft)
-                               end
+                       retieve_live_partial_types(mtype)
+               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 OrderedSet[MType].from(mtypes)
+                       sorted_mtypes.linearize(new ReverseTypeSorter(self.mainmodule))
+                       for mtype in sorted_mtypes do
+                               self.typeids[mtype] = self.typeids.length + 1
                        end
                        end
-                       var mclass_type: MClassType
-                       if mtype isa MNullableType then
-                               mclass_type = mtype.mtype.as(MClassType)
+               else
+                       for mtype in mtypes do
+                               self.typeids[mtype] = self.typeids.length
+                       end
+               end
+
+               # fts coloration for non-erased compilation
+               if modelbuilder.toolcontext.opt_bm_typing.value then
+                       var ft_coloring = new NaiveFTColoring(self.class_coloring)
+                       self.ft_colors = ft_coloring.colorize
+                       self.ft_tables = ft_coloring.build_ft_tables
+               else if modelbuilder.toolcontext.opt_phmod_typing.value then
+                       var ft_coloring = new FTModPerfectHashing(self.class_coloring)
+                       self.ft_colors = ft_coloring.colorize
+                       self.ft_masks = ft_coloring.compute_masks
+                       self.ft_tables = ft_coloring.build_ft_tables
+               else if modelbuilder.toolcontext.opt_phand_typing.value then
+                       var ft_coloring = new FTAndPerfectHashing(self.class_coloring)
+                       self.ft_colors = ft_coloring.colorize
+                       self.ft_masks = ft_coloring.compute_masks
+                       self.ft_tables = ft_coloring.build_ft_tables
+               else
+                       var ft_coloring = new FTColoring(self.class_coloring)
+                       self.ft_colors = ft_coloring.colorize
+                       self.ft_tables = ft_coloring.build_ft_tables
+               end
+               self.compile_color_consts(self.ft_colors.as(not null))
+
+               if modelbuilder.toolcontext.opt_generic_tree.value then
+                       # colorize live entries
+                       var entries_coloring
+                       if modelbuilder.toolcontext.opt_bm_typing.value then
+                               entries_coloring = new NaiveLiveEntryColoring
                        else
                        else
-                               mclass_type = mtype.as(MClassType)
+                               entries_coloring = new LiveEntryColoring
                        end
                        end
-                       # add virtual types to mtypes
-                       for vt in self.vt_tables[mclass_type.mclass] do
-                               if vt != null then
-                                       var anchored = vt.bound.anchor_to(self.mainmodule, mclass_type)
-                                       self.undead_types.add(anchored)
+                       self.livetypes_colors = entries_coloring.colorize(mtypes)
+                       self.livetypes_tables = entries_coloring.build_livetype_tables(mtypes)
+                       self.livetypes_tables_sizes = entries_coloring.livetypes_tables_sizes
+               else
+                       self.compile_unanchored_tables(mtypes)
+               end
+
+               # colorize types
+               if modelbuilder.toolcontext.opt_bm_typing.value then
+                       var type_coloring = new NaiveTypeColoring(self.mainmodule, mtypes)
+                       self.type_colors = type_coloring.colorize(mtypes)
+                       self.type_tables = type_coloring.build_type_tables(mtypes, type_colors)
+               else if modelbuilder.toolcontext.opt_phmod_typing.value then
+                       var type_coloring = new TypeModPerfectHashing(self.mainmodule, mtypes)
+                       self.type_colors = type_coloring.compute_masks(mtypes, typeids)
+                       self.type_tables = type_coloring.hash_type_tables(mtypes, typeids, type_colors)
+                       self.header.add_decl("#define HASH(mask, id) ((mask)%(id))")
+               else if modelbuilder.toolcontext.opt_phand_typing.value then
+                       var type_coloring = new TypeAndPerfectHashing(self.mainmodule, mtypes)
+                       self.type_colors = type_coloring.compute_masks(mtypes, typeids)
+                       self.type_tables = type_coloring.hash_type_tables(mtypes, typeids, type_colors)
+                       self.header.add_decl("#define HASH(mask, id) ((mask)&(id))")
+               else
+                       var type_coloring = new TypeColoring(self.mainmodule, mtypes)
+                       self.type_colors = type_coloring.colorize(mtypes)
+                       self.type_tables = type_coloring.build_type_tables(mtypes, type_colors)
+               end
+
+
+               return mtypes
+       end
+
+       protected fun compile_unanchored_tables(mtypes: Set[MType]) do
+               var mtype2anchored = new HashMap[MClassType, Set[MClassType]]
+
+               for mtype in self.runtime_type_analysis.live_types do
+                       for cd in mtype.collect_mclassdefs(self.mainmodule) do
+                               if self.live_unanchored_types.has_key(cd) then
+                                       if not mtype2anchored.has_key(mtype) then
+                                               mtype2anchored[mtype] = new HashSet[MClassType]
+                                       end
+                                       for unanchored in self.live_unanchored_types[cd] do
+                                               var anchored = unanchored.anchor_to(self.mainmodule, mtype)
+                                               if anchored isa MClassType then
+                                                       mtype2anchored[mtype].add(anchored)
+                                               else if anchored isa MNullableType then
+                                                       mtype2anchored[mtype].add(anchored.mtype.as(MClassType))
+                                               else
+                                                       print "NOT YET IMPLEMENTED: try compile_unanchored_tables with {unanchored}"
+                                               end
+                                       end
                                end
                        end
                end
                                end
                        end
                end
-               mtypes.add_all(self.undead_types)
 
 
-               # set type unique id
-               for mtype in mtypes do
-                       self.typeids[mtype] = self.typeids.length
+               if modelbuilder.toolcontext.opt_bm_typing.value then
+                       var unanchored_type_coloring = new NaiveUnanchoredTypeColoring
+                       self.unanchored_types_colors = unanchored_type_coloring.colorize(mtype2anchored)
+                       self.unanchored_types_tables = unanchored_type_coloring.build_tables(mtype2anchored)
+               else if modelbuilder.toolcontext.opt_phmod_typing.value then
+                       var unanchored_type_coloring = new UnanchoredTypeModPerfectHashing
+                       self.unanchored_types_colors = unanchored_type_coloring.colorize(mtype2anchored)
+                       self.unanchored_types_masks = unanchored_type_coloring.compute_masks(mtype2anchored)
+                       self.unanchored_types_tables = unanchored_type_coloring.build_tables(mtype2anchored)
+               else if modelbuilder.toolcontext.opt_phand_typing.value then
+                       var unanchored_type_coloring = new UnanchoredTypeAndPerfectHashing
+                       self.unanchored_types_colors = unanchored_type_coloring.colorize(mtype2anchored)
+                       self.unanchored_types_masks = unanchored_type_coloring.compute_masks(mtype2anchored)
+                       self.unanchored_types_tables = unanchored_type_coloring.build_tables(mtype2anchored)
+               else
+                       var unanchored_type_coloring = new UnanchoredTypeColoring
+                       self.unanchored_types_colors = unanchored_type_coloring.colorize(mtype2anchored)
+                       self.unanchored_types_tables = unanchored_type_coloring.build_tables(mtype2anchored)
                end
 
                end
 
-               # colorize live entries
-               var entries_coloring = new LiveEntryColoring
-               self.livetypes_colors = entries_coloring.colorize(mtypes)
-               self.livetypes_tables = entries_coloring.build_livetype_tables(mtypes)
-               self.livetypes_tables_sizes = entries_coloring.livetypes_tables_sizes
+               var unanchored_mtypes = new HashMap[MType, Int]
+               for mclass in modelbuilder.model.mclasses do
+                       var mtype = mclass.mclass_type
+                       if unanchored_types_colors.has_key(mtype) then
+                               unanchored_mtypes[mtype] = unanchored_types_colors[mtype]
+                       else
+                               unanchored_mtypes[mtype] = -1
+                       end
+               end
+               for mtype, color in unanchored_types_colors.as(not null) do
+                       unanchored_mtypes[mtype] = color
+               end
+               self.compile_color_consts(unanchored_mtypes)
 
 
-               # colorize types
-               var type_coloring = new TypeColoring(self.mainmodule, mtypes)
-               self.type_colors = type_coloring.colorize(mtypes)
-               self.type_tables = type_coloring.build_type_tables(mtypes, type_colors)
+               #print "tables"
+               #for k, v in unanchored_types_tables.as(not null) do
+               #       print "{k}: {v.join(", ")}"
+               #end
+               #print ""
+       end
 
 
-               return mtypes
+       fun retieve_live_partial_types(mtype: MType) do
+               # add formal types arguments to mtypes
+               if mtype isa MGenericType then
+                       for ft in mtype.arguments do
+                               if ft.need_anchor then
+                                       print("Why do we need anchor here ?")
+                                       abort
+                               end
+                               self.partial_types.add(ft)
+                               retieve_live_partial_types(ft)
+                       end
+               end
+               var mclass_type: MClassType
+               if mtype isa MNullableType then
+                       mclass_type = mtype.mtype.as(MClassType)
+               else
+                       mclass_type = mtype.as(MClassType)
+               end
+
+               # add virtual types to mtypes
+               for vt in self.vt_tables[mclass_type.mclass] do
+                       if vt != null then
+                               var anchored = vt.bound.anchor_to(self.mainmodule, mclass_type)
+                               self.partial_types.add(anchored)
+                       end
+               end
        end
 
        # declare live generic types tables selection
        end
 
        # declare live generic types tables selection
@@ -299,6 +475,8 @@ class SeparateCompiler
        # Separately compile all the method definitions of the module
        fun compile_module_to_c(mmodule: MModule)
        do
        # Separately compile all the method definitions of the module
        fun compile_module_to_c(mmodule: MModule)
        do
+               var old_module = self.mainmodule
+               self.mainmodule = mmodule
                for cd in mmodule.mclassdefs do
                        for pd in cd.mpropdefs do
                                if not pd isa MMethodDef then continue
                for cd in mmodule.mclassdefs do
                        for pd in cd.mpropdefs do
                                if not pd isa MMethodDef then continue
@@ -311,6 +489,7 @@ class SeparateCompiler
                                end
                        end
                end
                                end
                        end
                end
+               self.mainmodule = old_module
        end
 
        # Globaly compile the type structure of a live type
        end
 
        # Globaly compile the type structure of a live type
@@ -320,50 +499,53 @@ class SeparateCompiler
                var v = new SeparateCompilerVisitor(self)
                v.add_decl("/* runtime type {mtype} */")
 
                var v = new SeparateCompilerVisitor(self)
                v.add_decl("/* runtime type {mtype} */")
 
-               var mclass_type: MClassType
-               if mtype isa MNullableType then
-                       mclass_type = mtype.mtype.as(MClassType)
-               else
-                       mclass_type = mtype.as(MClassType)
-               end
-
                # extern const struct type_X
                self.header.add_decl("extern const struct type_{c_name} type_{c_name};")
                self.header.add_decl("struct type_{c_name} \{")
                self.header.add_decl("int id;")
                # extern const struct type_X
                self.header.add_decl("extern const struct type_{c_name} type_{c_name};")
                self.header.add_decl("struct type_{c_name} \{")
                self.header.add_decl("int id;")
+               self.header.add_decl("const char *name;")
                self.header.add_decl("int color;")
                self.header.add_decl("int color;")
-               self.header.add_decl("int livecolor;")
                self.header.add_decl("short int is_nullable;")
                self.header.add_decl("short int is_nullable;")
+               if modelbuilder.toolcontext.opt_generic_tree.value then
+                       self.header.add_decl("int livecolor;")
+               else
+                       self.header.add_decl("const struct unanchored_table_{c_name} *types;")
+               end
                self.header.add_decl("const struct vts_table_{c_name} *vts_table;")
                self.header.add_decl("const struct fts_table_{c_name} *fts_table;")
                self.header.add_decl("int table_size;")
                self.header.add_decl("int type_table[{self.type_tables[mtype].length}];")
                self.header.add_decl("\};")
 
                self.header.add_decl("const struct vts_table_{c_name} *vts_table;")
                self.header.add_decl("const struct fts_table_{c_name} *fts_table;")
                self.header.add_decl("int table_size;")
                self.header.add_decl("int type_table[{self.type_tables[mtype].length}];")
                self.header.add_decl("\};")
 
-               # extern const struct vts_table_X vts_table_X
-               self.header.add_decl("extern const struct vts_table_{c_name} vts_table_{c_name};")
-               self.header.add_decl("struct vts_table_{c_name} \{")
-               self.header.add_decl("struct type *vts[{self.vt_tables[mclass_type.mclass].length}];")
-               self.header.add_decl("\};")
-
-               # extern const struct fst_table_X fst_table_X
-               self.header.add_decl("extern const struct fts_table_{c_name} fts_table_{c_name};")
-               self.header.add_decl("struct fts_table_{c_name} \{")
-               self.header.add_decl("struct type *fts[{self.ft_tables[mclass_type.mclass].length}];")
-               self.header.add_decl("\};")
-
                # const struct type_X
                v.add_decl("const struct type_{c_name} type_{c_name} = \{")
                v.add_decl("{self.typeids[mtype]},")
                # const struct type_X
                v.add_decl("const struct type_{c_name} type_{c_name} = \{")
                v.add_decl("{self.typeids[mtype]},")
+               v.add_decl("\"{mtype}\", /* class_name_string */")
                v.add_decl("{self.type_colors[mtype]},")
                v.add_decl("{self.type_colors[mtype]},")
-               v.add_decl("{self.livetypes_colors[mtype]},")
                if mtype isa MNullableType then
                        v.add_decl("1,")
                else
                        v.add_decl("0,")
                end
                if mtype isa MNullableType then
                        v.add_decl("1,")
                else
                        v.add_decl("0,")
                end
-               v.add_decl("&vts_table_{c_name},")
-               v.add_decl("&fts_table_{c_name},")
+               if modelbuilder.toolcontext.opt_generic_tree.value then
+                       v.add_decl("{self.livetypes_colors[mtype]},")
+               else
+                       if compile_type_unanchored_table(mtype) then
+                               v.add_decl("&unanchored_table_{c_name},")
+                       else
+                               v.add_decl("NULL,")
+                       end
+               end
+               if compile_type_vts_table(mtype) then
+                       v.add_decl("&vts_table_{c_name},")
+               else
+                       v.add_decl("NULL,")
+               end
+               if compile_type_fts_table(mtype) then
+                       v.add_decl("&fts_table_{c_name},")
+               else
+                       v.add_decl("NULL,")
+               end
                v.add_decl("{self.type_tables[mtype].length},")
                v.add_decl("\{")
                for stype in self.type_tables[mtype] do
                v.add_decl("{self.type_tables[mtype].length},")
                v.add_decl("\{")
                for stype in self.type_tables[mtype] do
@@ -375,15 +557,9 @@ class SeparateCompiler
                end
                v.add_decl("\},")
                v.add_decl("\};")
                end
                v.add_decl("\},")
                v.add_decl("\};")
-
-               build_fts_table(mtype, v)
-               build_vts_table(mtype, v)
        end
 
        end
 
-       # const struct fst_table_X fst_table_X
-       private fun build_fts_table(mtype: MType, v: SeparateCompilerVisitor) do
-               v.add_decl("const struct fts_table_{mtype.c_name} fts_table_{mtype.c_name} = \{")
-               v.add_decl("\{")
+       protected fun compile_type_fts_table(mtype: MType): Bool do
 
                var mclass_type: MClassType
                if mtype isa MNullableType then
 
                var mclass_type: MClassType
                if mtype isa MNullableType then
@@ -391,7 +567,24 @@ class SeparateCompiler
                else
                        mclass_type = mtype.as(MClassType)
                end
                else
                        mclass_type = mtype.as(MClassType)
                end
+               if self.ft_tables[mclass_type.mclass].is_empty then return false
 
 
+               # extern const struct fst_table_X fst_table_X
+               self.header.add_decl("extern const struct fts_table_{mtype.c_name} fts_table_{mtype.c_name};")
+               self.header.add_decl("struct fts_table_{mtype.c_name} \{")
+               if modelbuilder.toolcontext.opt_phmod_typing.value or modelbuilder.toolcontext.opt_phand_typing.value then
+                       self.header.add_decl("int mask;")
+               end
+               self.header.add_decl("struct type *fts[{self.ft_tables[mclass_type.mclass].length}];")
+               self.header.add_decl("\};")
+
+               # const struct fts_table_X fts_table_X
+               var v = new_visitor
+               v.add_decl("const struct fts_table_{mtype.c_name} fts_table_{mtype.c_name} = \{")
+               if modelbuilder.toolcontext.opt_phmod_typing.value or modelbuilder.toolcontext.opt_phand_typing.value then
+                       v.add_decl("{self.ft_masks[mclass_type.mclass]},")
+               end
+               v.add_decl("\{")
                for ft in self.ft_tables[mclass_type.mclass] do
                        if ft == null then
                                v.add_decl("NULL, /* empty */")
                for ft in self.ft_tables[mclass_type.mclass] do
                        if ft == null then
                                v.add_decl("NULL, /* empty */")
@@ -411,12 +604,10 @@ class SeparateCompiler
                end
                v.add_decl("\},")
                v.add_decl("\};")
                end
                v.add_decl("\},")
                v.add_decl("\};")
+               return true
        end
 
        end
 
-       # const struct vts_table_X vts_table_X
-       private fun build_vts_table(mtype: MType, v: SeparateCompilerVisitor) do
-               v.add_decl("const struct vts_table_{mtype.c_name} vts_table_{mtype.c_name} = \{")
-               v.add_decl("\{")
+       protected fun compile_type_vts_table(mtype: MType): Bool do
 
                var mclass_type: MClassType
                if mtype isa MNullableType then
 
                var mclass_type: MClassType
                if mtype isa MNullableType then
@@ -424,6 +615,24 @@ class SeparateCompiler
                else
                        mclass_type = mtype.as(MClassType)
                end
                else
                        mclass_type = mtype.as(MClassType)
                end
+               if self.vt_tables[mclass_type.mclass].is_empty then return false
+
+               # extern const struct vts_table_X vts_table_X
+               self.header.add_decl("extern const struct vts_table_{mtype.c_name} vts_table_{mtype.c_name};")
+               self.header.add_decl("struct vts_table_{mtype.c_name} \{")
+               if modelbuilder.toolcontext.opt_phmod_typing.value or modelbuilder.toolcontext.opt_phand_typing.value then
+                       self.header.add_decl("int mask;")
+               end
+               self.header.add_decl("struct type *vts[{self.vt_tables[mclass_type.mclass].length}];")
+               self.header.add_decl("\};")
+
+               # const struct vts_table_X vts_table_X
+               var v = new_visitor
+               v.add_decl("const struct vts_table_{mtype.c_name} vts_table_{mtype.c_name} = \{")
+               if modelbuilder.toolcontext.opt_phmod_typing.value or modelbuilder.toolcontext.opt_phand_typing.value then
+                       v.add_decl("{vt_masks[mclass_type.mclass]},")
+               end
+               v.add_decl("\{")
 
                for vt in self.vt_tables[mclass_type.mclass] do
                        if vt == null then
 
                for vt in self.vt_tables[mclass_type.mclass] do
                        if vt == null then
@@ -435,30 +644,77 @@ class SeparateCompiler
                                        print "No bound found for virtual type {vt} ?"
                                        abort
                                else
                                        print "No bound found for virtual type {vt} ?"
                                        abort
                                else
-                                       var ntype = bound
-                                       if ntype isa MNullableType then ntype = ntype.mtype
-                                       if ntype isa MVirtualType then
-                                               bound = ntype.anchor_to(self.mainmodule, mclass_type)
-                                       else if ntype isa MParameterType then
-                                               bound = ntype.anchor_to(self.mainmodule, mclass_type)
-                                       else if ntype isa MGenericType and bound.need_anchor then
-                                               bound = ntype.anchor_to(self.mainmodule, mclass_type)
-                                       else if ntype isa MClassType then
+                                       var is_nullable = ""
+                                       if bound isa MNullableType then
+                                               bound = bound.mtype
+                                               is_nullable = "nullable_"
+                                       end
+                                       if bound isa MVirtualType then
+                                               bound = bound.anchor_to(self.mainmodule, mclass_type)
+                                       else if bound isa MParameterType then
+                                               bound = bound.anchor_to(self.mainmodule, mclass_type)
+                                       else if bound isa MGenericType and bound.need_anchor then
+                                               bound = bound.anchor_to(self.mainmodule, mclass_type)
+                                       else if bound isa MClassType then
                                        else
                                        else
-                                               print "NOT YET IMPLEMENTED: mtype_to_livetype with type: {ntype}"
+                                               print "NOT YET IMPLEMENTED: mtype_to_livetype with type: {bound}"
                                                abort
                                        end
 
                                        if self.typeids.has_key(bound) then
                                                abort
                                        end
 
                                        if self.typeids.has_key(bound) then
-                                               v.add_decl("(struct type*)&type_{bound.c_name}, /* {ntype} */")
+                                               v.add_decl("(struct type*)&type_{is_nullable}{bound.c_name}, /* {bound} */")
                                        else
                                        else
-                                               v.add_decl("NULL, /* dead type {ntype} */")
+                                               v.add_decl("NULL, /* dead type {bound} */")
                                        end
                                end
                        end
                end
                v.add_decl("\},")
                v.add_decl("\};")
                                        end
                                end
                        end
                end
                v.add_decl("\},")
                v.add_decl("\};")
+               return true
+       end
+
+       fun compile_type_unanchored_table(mtype: MType): Bool do
+
+               var mclass_type: MClassType
+               if mtype isa MNullableType then
+                       mclass_type = mtype.mtype.as(MClassType)
+               else
+                       mclass_type = mtype.as(MClassType)
+               end
+               if not self.unanchored_types_tables.has_key(mclass_type) then return false
+
+               # extern const struct unanchored_table_X unanchored_table_X
+               self.header.add_decl("extern const struct unanchored_table_{mtype.c_name} unanchored_table_{mtype.c_name};")
+
+               self.header.add_decl("struct unanchored_table_{mtype.c_name} \{")
+               if modelbuilder.toolcontext.opt_phmod_typing.value or modelbuilder.toolcontext.opt_phand_typing.value then
+                       self.header.add_decl("int mask;")
+               end
+               self.header.add_decl("struct type *types[{self.unanchored_types_tables[mclass_type].length}];")
+               self.header.add_decl("\};")
+
+               # const struct fts_table_X fts_table_X
+               var v = new_visitor
+               v.add_decl("const struct unanchored_table_{mtype.c_name} unanchored_table_{mtype.c_name} = \{")
+               if modelbuilder.toolcontext.opt_phmod_typing.value or modelbuilder.toolcontext.opt_phand_typing.value then
+                       v.add_decl("{self.unanchored_types_masks[mclass_type]},")
+               end
+               v.add_decl("\{")
+               for t in self.unanchored_types_tables[mclass_type] do
+                       if t == null then
+                               v.add_decl("NULL, /* empty */")
+                       else
+                               if self.typeids.has_key(t) then
+                                       v.add_decl("(struct type*)&type_{t.c_name}, /* {t} */")
+                               else
+                                       v.add_decl("NULL, /* empty ({t} not a live type) */")
+                               end
+                       end
+               end
+               v.add_decl("\},")
+               v.add_decl("\};")
+               return true
        end
 
        # Globally compile the table of the class mclass
        end
 
        # Globally compile the table of the class mclass
@@ -471,7 +727,7 @@ class SeparateCompiler
 
                var vft = self.method_tables[mclass]
                var attrs = self.attr_tables[mclass]
 
                var vft = self.method_tables[mclass]
                var attrs = self.attr_tables[mclass]
-               var v = new SeparateCompilerVisitor(self)
+               var v = new_visitor
 
                v.add_decl("/* runtime class {c_name} */")
                var idnum = classids.length
 
                v.add_decl("/* runtime class {c_name} */")
                var idnum = classids.length
@@ -566,6 +822,22 @@ class SeparateCompiler
                self.generate_init_attr(v, res, mtype)
                v.add("return {res};")
                v.add("\}")
                self.generate_init_attr(v, res, mtype)
                v.add("return {res};")
                v.add("\}")
+
+               generate_check_init_instance(mtype)
+       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.header.add_decl("void CHECK_NEW_{c_name}({mtype.ctype});")
+               v.add_decl("/* allocate {mtype} */")
+               v.add_decl("void CHECK_NEW_{c_name}({mtype.ctype} {res}) \{")
+               self.generate_check_attr(v, res, mtype)
+               v.add("\}")
        end
 
        redef fun new_visitor do return new SeparateCompilerVisitor(self)
        end
 
        redef fun new_visitor do return new SeparateCompilerVisitor(self)
@@ -847,10 +1119,9 @@ class SeparateCompilerVisitor
                        self.add("\} else \{")
                end
 
                        self.add("\} else \{")
                end
 
-               var color = self.compiler.as(SeparateCompiler).method_colors[mmethod]
                var r
                if ret == null then r = "void" else r = ret.ctype
                var r
                if ret == null then r = "void" else r = ret.ctype
-               var call = "(({r} (*)({s}))({arguments.first}->class->vft[{color}]))({ss}) /* {mmethod} on {arguments.first.inspect}*/"
+               var call = "(({r} (*)({s}))({arguments.first}->class->vft[{mmethod.const_color}]))({ss}) /* {mmethod} on {arguments.first.inspect}*/"
 
                if res != null then
                        self.add("{res} = {call};")
 
                if res != null then
                        self.add("{res} = {call};")
@@ -912,7 +1183,7 @@ class SeparateCompilerVisitor
        do
                self.check_recv_notnull(recv)
                var res = self.new_var(bool_type)
        do
                self.check_recv_notnull(recv)
                var res = self.new_var(bool_type)
-               self.add("{res} = {recv}->attrs[{self.compiler.as(SeparateCompiler).attr_colors[a]}] != NULL; /* {a} on {recv.inspect}*/")
+               self.add("{res} = {recv}->attrs[{a.const_color}] != NULL; /* {a} on {recv.inspect}*/")
                return res
        end
 
                return res
        end
 
@@ -929,7 +1200,7 @@ class SeparateCompilerVisitor
                var cret = self.object_type.as_nullable
                var res = self.new_var(cret)
                res.mcasttype = ret
                var cret = self.object_type.as_nullable
                var res = self.new_var(cret)
                res.mcasttype = ret
-               self.add("{res} = {recv}->attrs[{self.compiler.as(SeparateCompiler).attr_colors[a]}]; /* {a} on {recv.inspect} */")
+               self.add("{res} = {recv}->attrs[{a.const_color}]; /* {a} on {recv.inspect} */")
 
                # Check for Uninitialized attribute
                if not ret isa MNullableType and not self.compiler.modelbuilder.toolcontext.opt_no_check_initialization.value then
 
                # Check for Uninitialized attribute
                if not ret isa MNullableType and not self.compiler.modelbuilder.toolcontext.opt_no_check_initialization.value then
@@ -954,7 +1225,7 @@ class SeparateCompilerVisitor
 
                # Adapt the value to the declared type
                value = self.autobox(value, mtype)
 
                # Adapt the value to the declared type
                value = self.autobox(value, mtype)
-               var attr = "{recv}->attrs[{self.compiler.as(SeparateCompiler).attr_colors[a]}]"
+               var attr = "{recv}->attrs[{a.const_color}]"
                if mtype.ctype != "val*" then
                        assert mtype isa MClassType
                        # The attribute is primitive, thus we store it in a box
                if mtype.ctype != "val*" then
                        assert mtype isa MClassType
                        # The attribute is primitive, thus we store it in a box
@@ -986,11 +1257,17 @@ class SeparateCompilerVisitor
                        end
 
                        if ntype isa MParameterType then
                        end
 
                        if ntype isa MParameterType then
-                               var ftcolor = compiler.ft_colors[ntype]
-                               buffer.append("[self->type->fts_table->fts[{ftcolor}]->livecolor]")
+                               if compiler.modelbuilder.toolcontext.opt_phmod_typing.value or compiler.modelbuilder.toolcontext.opt_phand_typing.value then
+                                       buffer.append("[self->type->fts_table->types[HASH(self->type->fts_table->mask, {ntype.const_color})]->livecolor]")
+                               else
+                                       buffer.append("[self->type->fts_table->types[{ntype.const_color}]->livecolor]")
+                               end
                        else if ntype isa MVirtualType then
                        else if ntype isa MVirtualType then
-                               var vtcolor = compiler.vt_colors[ntype.mproperty.as(MVirtualTypeProp)]
-                               buffer.append("[self->type->vts_table->vts[{vtcolor}]->livecolor]")
+                               if compiler.modelbuilder.toolcontext.opt_phmod_typing.value or compiler.modelbuilder.toolcontext.opt_phand_typing.value then
+                                       buffer.append("[self->type->vts_table->types[HASH(self->type->vts_table->mask, {ntype.mproperty.const_color})]->livecolor]")
+                               else
+                                       buffer.append("[self->type->vts_table->types[{ntype.mproperty.const_color}]->livecolor]")
+                               end
                        else if ntype isa MGenericType and ntype.need_anchor then
                                var bbuff = new Buffer
                                retrieve_anchored_livetype(ntype, bbuff)
                        else if ntype isa MGenericType and ntype.need_anchor then
                                var bbuff = new Buffer
                                retrieve_anchored_livetype(ntype, bbuff)
@@ -1008,17 +1285,36 @@ class SeparateCompilerVisitor
        do
                var compiler = self.compiler.as(SeparateCompiler)
                if mtype isa MGenericType and mtype.need_anchor then
        do
                var compiler = self.compiler.as(SeparateCompiler)
                if mtype isa MGenericType and mtype.need_anchor then
-                       var buff = new Buffer
-                       retrieve_anchored_livetype(mtype, buff)
-                       mtype = self.anchor(mtype).as(MClassType)
-                       return self.new_expr("NEW_{mtype.mclass.c_name}((struct type *) livetypes_{mtype.mclass.c_name}{buff.to_s})", mtype)
+                       if compiler.modelbuilder.toolcontext.opt_generic_tree.value then
+                               var buff = new Buffer
+                               retrieve_anchored_livetype(mtype, buff)
+                               mtype = self.anchor(mtype).as(MClassType)
+                               return self.new_expr("NEW_{mtype.mclass.c_name}((struct type *) livetypes_{mtype.mclass.c_name}{buff.to_s})", mtype)
+                       else
+                               link_unanchored_type(self.frame.mpropdef.mclassdef, mtype)
+                               var recv = self.frame.arguments.first
+                               var recv_boxed = self.autobox(recv, self.object_type)
+                               if compiler.modelbuilder.toolcontext.opt_phmod_typing.value or compiler.modelbuilder.toolcontext.opt_phand_typing.value then
+                                       return self.new_expr("NEW_{mtype.mclass.c_name}((struct type *) {recv_boxed}->type->unanchored_table->types[HASH({recv_boxed}->type->unanchored_table->mask, {mtype.mclass.mclass_type.const_color})])", mtype)
+                               else
+                                       return self.new_expr("NEW_{mtype.mclass.c_name}((struct type *) {recv_boxed}->type->unanchored_table->types[{mtype.mclass.mclass_type.const_color}])", mtype)
+                               end
+                       end
                end
                compiler.undead_types.add(mtype)
                return self.new_expr("NEW_{mtype.mclass.c_name}((struct type *) &type_{mtype.c_name})", mtype)
        end
 
                end
                compiler.undead_types.add(mtype)
                return self.new_expr("NEW_{mtype.mclass.c_name}((struct type *) &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.add("CHECK_NEW_{mtype.mclass.c_name}({value});")
+       end
+
+
        redef fun type_test(value, mtype)
        do
        redef fun type_test(value, mtype)
        do
+               self.add("/* {value.inspect} isa {mtype} */")
                var compiler = self.compiler.as(SeparateCompiler)
 
                var recv = self.frame.arguments.first
                var compiler = self.compiler.as(SeparateCompiler)
 
                var recv = self.frame.arguments.first
@@ -1026,42 +1322,68 @@ class SeparateCompilerVisitor
 
                var res = self.new_var(bool_type)
 
 
                var res = self.new_var(bool_type)
 
+               var type_struct = self.get_name("type_struct")
+               self.add_decl("struct type* {type_struct};")
                var cltype = self.get_name("cltype")
                self.add_decl("int {cltype};")
                var idtype = self.get_name("idtype")
                self.add_decl("int {idtype};")
                var cltype = self.get_name("cltype")
                self.add_decl("int {cltype};")
                var idtype = self.get_name("idtype")
                self.add_decl("int {idtype};")
-
                var is_nullable = self.get_name("is_nullable")
                self.add_decl("short int {is_nullable};")
 
                var boxed = self.autobox(value, self.object_type)
 
                var is_nullable = self.get_name("is_nullable")
                self.add_decl("short int {is_nullable};")
 
                var boxed = self.autobox(value, self.object_type)
 
+               if not compiler.modelbuilder.toolcontext.opt_generic_tree.value and mtype.need_anchor then
+                       link_unanchored_type(self.frame.mpropdef.mclassdef, mtype)
+               end
+
                var ntype = mtype
                if ntype isa MNullableType then
                        ntype = ntype.mtype
                end
 
                if ntype isa MParameterType then
                var ntype = mtype
                if ntype isa MNullableType then
                        ntype = ntype.mtype
                end
 
                if ntype isa MParameterType then
-                       var ftcolor = compiler.ft_colors[ntype]
-                       self.add("{cltype} = {recv_boxed}->type->fts_table->fts[{ftcolor}]->color;")
-                       self.add("{idtype} = {recv_boxed}->type->fts_table->fts[{ftcolor}]->id;")
-                       self.add("{is_nullable} = {recv_boxed}->type->fts_table->fts[{ftcolor}]->is_nullable;")
+                       if compiler.modelbuilder.toolcontext.opt_phmod_typing.value or compiler.modelbuilder.toolcontext.opt_phand_typing.value then
+                               self.add("{type_struct} = {recv_boxed}->type->fts_table->types[HASH({recv_boxed}->type->fts_table->mask, {ntype.const_color})];")
+                       else
+                               self.add("{type_struct} = {recv_boxed}->type->fts_table->types[{ntype.const_color}];")
+                       end
+                       self.add("{cltype} = {type_struct}->color;")
+                       self.add("{idtype} = {type_struct}->id;")
+                       self.add("{is_nullable} = {type_struct}->is_nullable;")
                else if ntype isa MGenericType and ntype.need_anchor then
                else if ntype isa MGenericType and ntype.need_anchor then
-                       var buff = new Buffer
-                       retrieve_anchored_livetype(ntype, buff)
-                       self.add("{cltype} = livetypes_{ntype.mclass.c_name}{buff.to_s}->color;")
-                       self.add("{idtype} = livetypes_{ntype.mclass.c_name}{buff.to_s}->id;")
-                       self.add("{is_nullable} = livetypes_{ntype.mclass.c_name}{buff.to_s}->is_nullable;")
+                       if compiler.modelbuilder.toolcontext.opt_generic_tree.value then
+                               var buff = new Buffer
+                               retrieve_anchored_livetype(ntype, buff)
+                               self.add("{type_struct} = (struct type*)livetypes_{ntype.mclass.c_name}{buff.to_s};")
+                               self.add("{cltype} = {type_struct}->color;")
+                               self.add("{idtype} = {type_struct}->id;")
+                               self.add("{is_nullable} = {type_struct}->is_nullable;")
+                       else
+                               if compiler.modelbuilder.toolcontext.opt_phmod_typing.value or compiler.modelbuilder.toolcontext.opt_phand_typing.value then
+                                       self.add("{type_struct} = {recv_boxed}->type->unanchored_table->types[HASH({recv_boxed}->type->unanchored_table->mask, {ntype.mclass.mclass_type.const_color})];")
+                               else
+                                       self.add("{type_struct} = {recv_boxed}->type->unanchored_table->types[{ntype.mclass.mclass_type.const_color}];")
+                               end
+                               self.add("{cltype} = {type_struct}->color;")
+                               self.add("{idtype} = {type_struct}->id;")
+                               self.add("{is_nullable} = {type_struct}->is_nullable;")
+                       end
                else if ntype isa MClassType then
                        compiler.undead_types.add(mtype)
                        self.add("{cltype} = type_{mtype.c_name}.color;")
                        self.add("{idtype} = type_{mtype.c_name}.id;")
                        self.add("{is_nullable} = type_{mtype.c_name}.is_nullable;")
                else if ntype isa MVirtualType then
                else if ntype isa MClassType then
                        compiler.undead_types.add(mtype)
                        self.add("{cltype} = type_{mtype.c_name}.color;")
                        self.add("{idtype} = type_{mtype.c_name}.id;")
                        self.add("{is_nullable} = type_{mtype.c_name}.is_nullable;")
                else if ntype isa MVirtualType then
-                       var vtcolor = compiler.vt_colors[ntype.mproperty.as(MVirtualTypeProp)]
-                       self.add("{cltype} = {recv_boxed}->type->vts_table->vts[{vtcolor}]->color;")
-                       self.add("{idtype} = {recv_boxed}->type->vts_table->vts[{vtcolor}]->id;")
-                       self.add("{is_nullable} = {recv_boxed}->type->vts_table->vts[{vtcolor}]->is_nullable;")
+                       var vtcolor = ntype.mproperty.const_color
+                       if compiler.modelbuilder.toolcontext.opt_phmod_typing.value or compiler.modelbuilder.toolcontext.opt_phand_typing.value then
+                               self.add("{type_struct} = {recv_boxed}->type->vts_table->types[HASH({recv_boxed}->type->vts_table->mask, {vtcolor})];")
+                       else
+                               self.add("{type_struct} = {recv_boxed}->type->vts_table->types[{vtcolor}];")
+                       end
+                       self.add("{cltype} = {type_struct}->color;")
+                       self.add("{idtype} = {type_struct}->id;")
+                       self.add("{is_nullable} = {type_struct}->is_nullable;")
                else
                        self.add("printf(\"NOT YET IMPLEMENTED: type_test(%s, {mtype}).\\n\", \"{boxed.inspect}\"); exit(1);")
                end
                else
                        self.add("printf(\"NOT YET IMPLEMENTED: type_test(%s, {mtype}).\\n\", \"{boxed.inspect}\"); exit(1);")
                end
@@ -1074,6 +1396,9 @@ class SeparateCompilerVisitor
                self.add("if({boxed} == NULL) \{")
                self.add("{res} = {is_nullable};")
                self.add("\} else \{")
                self.add("if({boxed} == NULL) \{")
                self.add("{res} = {is_nullable};")
                self.add("\} else \{")
+               if compiler.modelbuilder.toolcontext.opt_phmod_typing.value or compiler.modelbuilder.toolcontext.opt_phand_typing.value then
+                       self.add("{cltype} = HASH({boxed}->type->color, {idtype});")
+               end
                self.add("if({cltype} >= {boxed}->type->table_size) \{")
                self.add("{res} = 0;")
                self.add("\} else \{")
                self.add("if({cltype} >= {boxed}->type->table_size) \{")
                self.add("{res} = 0;")
                self.add("\} else \{")
@@ -1111,8 +1436,12 @@ class SeparateCompilerVisitor
        redef fun class_name_string(value)
        do
                var res = self.get_name("var_class_name")
        redef fun class_name_string(value)
        do
                var res = self.get_name("var_class_name")
-               self.add_decl("const char *{res};")
-               self.add("{res} = class_names[{value}->type->id];")
+               self.add_decl("const char* {res};")
+               if value.mtype.ctype == "val*" then
+                       self.add "{res} = {value} == NULL ? \"null\" : {value}->type->name;"
+               else
+                       self.add "{res} = type_{value.mtype.c_name}.name;"
+               end
                return res
        end
 
                return res
        end
 
@@ -1222,27 +1551,49 @@ class SeparateCompilerVisitor
 
        redef fun array_instance(array, elttype)
        do
 
        redef fun array_instance(array, elttype)
        do
-               var compiler = self.compiler.as(SeparateCompiler)
                var nclass = self.get_class("NativeArray")
                var nclass = self.get_class("NativeArray")
-               elttype = self.anchor(elttype)
-               var arraytype = self.get_class("Array").get_mtype([elttype])
+               var arrayclass = self.get_class("Array")
+               var arraytype = arrayclass.get_mtype([elttype])
                var res = self.init_instance(arraytype)
                self.add("\{ /* {res} = array_instance Array[{elttype}] */")
                var res = self.init_instance(arraytype)
                self.add("\{ /* {res} = array_instance Array[{elttype}] */")
-               var nat = self.new_var(self.get_class("NativeArray").get_mtype([elttype]))
-               nat.is_exact = true
-               compiler.undead_types.add(nat.mtype.as(MClassType))
-               self.add("{nat} = NEW_{nclass.c_name}({array.length}, (struct type *) &type_{nat.mtype.c_name});")
+               var length = self.int_instance(array.length)
+               var nat = native_array_instance(elttype, length)
                for i in [0..array.length[ do
                        var r = self.autobox(array[i], self.object_type)
                        self.add("((struct instance_{nclass.c_name}*){nat})->values[{i}] = (val*) {r};")
                end
                for i in [0..array.length[ do
                        var r = self.autobox(array[i], self.object_type)
                        self.add("((struct instance_{nclass.c_name}*){nat})->values[{i}] = (val*) {r};")
                end
-               var length = self.int_instance(array.length)
-               self.send(self.get_property("with_native", arraytype), [res, nat, length])
+               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
 
                self.check_init_instance(res, arraytype)
                self.add("\}")
                return res
        end
 
+       fun native_array_instance(elttype: MType, length: RuntimeVariable): RuntimeVariable
+       do
+               var mtype = self.get_class("NativeArray").get_mtype([elttype])
+               assert mtype isa MGenericType
+               var compiler = self.compiler.as(SeparateCompiler)
+               if mtype.need_anchor then
+                       if compiler.modelbuilder.toolcontext.opt_generic_tree.value then
+                               var buff = new Buffer
+                               retrieve_anchored_livetype(mtype, buff)
+                               mtype = self.anchor(mtype).as(MClassType)
+                               return self.new_expr("NEW_{mtype.mclass.c_name}({length}, (struct type *) livetypes_{mtype.mclass.c_name}{buff.to_s})", mtype)
+                       else
+                               link_unanchored_type(self.frame.mpropdef.mclassdef, mtype)
+                               var recv = self.frame.arguments.first
+                               var recv_boxed = self.autobox(recv, self.object_type)
+                               if compiler.modelbuilder.toolcontext.opt_phmod_typing.value or compiler.modelbuilder.toolcontext.opt_phand_typing.value then
+                                       return self.new_expr("NEW_{mtype.mclass.c_name}({length}, (struct type *) {recv_boxed}->type->unanchored_table->types[HASH({recv_boxed}->type->unanchored_table->mask, {mtype.mclass.mclass_type.const_color})])", mtype)
+                               else
+                                       return self.new_expr("NEW_{mtype.mclass.c_name}({length}, (struct type *) {recv_boxed}->type->unanchored_table->types[{mtype.mclass.mclass_type.const_color}])", mtype)
+                               end
+                       end
+               end
+               compiler.undead_types.add(mtype)
+               return self.new_expr("NEW_{mtype.mclass.c_name}({length}, (struct type *) &type_{mtype.c_name})", mtype)
+       end
+
        redef fun native_array_def(pname, ret_type, arguments)
        do
                var elttype = arguments.first.mtype
        redef fun native_array_def(pname, ret_type, arguments)
        do
                var elttype = arguments.first.mtype
@@ -1267,9 +1618,31 @@ class SeparateCompilerVisitor
                var compiler = self.compiler.as(SeparateCompiler)
                compiler.undead_types.add(ret)
                var mclass = self.get_class("ArrayCapable")
                var compiler = self.compiler.as(SeparateCompiler)
                compiler.undead_types.add(ret)
                var mclass = self.get_class("ArrayCapable")
-               var ft = mclass.mclass_type.arguments.first.as(MParameterType)
-               var color = compiler.ft_colors[ft]
-               self.ret(self.new_expr("NEW_{ret.mclass.c_name}({arguments[1]}, (struct type*) livetypes_array__NativeArray[self->type->fts_table->fts[{color}]->livecolor])", ret_type))
+               var nclass = self.get_class("NativeArray")
+
+               if compiler.modelbuilder.toolcontext.opt_generic_tree.value then
+                       var ft = mclass.mclass_type.arguments.first.as(MParameterType)
+                       self.ret(self.new_expr("NEW_{nclass.c_name}({arguments[1]}, (struct type*) livetypes_array__NativeArray[self->type->fts_table->types[{ft.const_color}]->livecolor])", ret_type))
+               else
+                       var res = nclass.get_mtype(mclass.mclass_type.arguments)
+                       link_unanchored_type(self.frame.mpropdef.mclassdef, res)
+                       var recv = self.frame.arguments.first
+                       var recv_boxed = self.autobox(recv, self.object_type)
+                       if compiler.modelbuilder.toolcontext.opt_phmod_typing.value or compiler.modelbuilder.toolcontext.opt_phand_typing.value then
+                               self.ret(self.new_expr("NEW_{nclass.c_name}({arguments[1]}, (struct type *) {recv_boxed}->type->unanchored_table->types[HASH({recv_boxed}->type->unanchored_table->mask, {nclass.mclass_type.const_color})])", ret_type))
+                       else
+                               self.ret(self.new_expr("NEW_{nclass.c_name}({arguments[1]}, (struct type *) {recv_boxed}->type->unanchored_table->types[{nclass.mclass_type.const_color}])", ret_type))
+                       end
+               end
+       end
+
+       fun link_unanchored_type(mclassdef: MClassDef, mtype: MType) do
+               assert mtype.need_anchor
+               var compiler = self.compiler.as(SeparateCompiler)
+               if not compiler.live_unanchored_types.has_key(self.frame.mpropdef.mclassdef) then
+                       compiler.live_unanchored_types[self.frame.mpropdef.mclassdef] = new HashSet[MType]
+               end
+               compiler.live_unanchored_types[self.frame.mpropdef.mclassdef].add(mtype)
        end
 end
 
        end
 end
 
@@ -1284,3 +1657,42 @@ redef class MClass
        end
        private var c_name_cache: nullable String
 end
        end
        private var c_name_cache: nullable String
 end
+
+redef class MType
+       fun const_color: String do return "COLOR_{c_name}"
+end
+
+redef class MParameterType
+       redef fun c_name
+       do
+               var res = self.c_name_cache
+               if res != null then return res
+               res = "{self.mclass.c_name}_FT{self.rank}"
+               self.c_name_cache = res
+               return res
+       end
+end
+
+redef class MNullableType
+       redef fun c_name
+       do
+               var res = self.c_name_cache
+               if res != null then return res
+               res = "nullable_{self.mtype.c_name}"
+               self.c_name_cache = res
+               return res
+       end
+end
+
+redef class MProperty
+       fun c_name: String do
+               var res = self.c_name_cache
+               if res != null then return res
+               res = "{self.intro.c_name}"
+               self.c_name_cache = res
+               return res
+       end
+       private var c_name_cache: nullable String
+
+       fun const_color: String do return "COLOR_{c_name}"
+end