X-Git-Url: http://nitlanguage.org diff --git a/src/compiler/separate_compiler.nit b/src/compiler/separate_compiler.nit index e0500e2..2d98fb6 100644 --- a/src/compiler/separate_compiler.nit +++ b/src/compiler/separate_compiler.nit @@ -29,6 +29,9 @@ redef class ToolContext var opt_no_union_attribute = new OptionBool("Put primitive attibutes in a box instead of an union", "--no-union-attribute") # --no-shortcut-equate var opt_no_shortcut_equate = new OptionBool("Always call == in a polymorphic way", "--no-shortcut-equal") + # --colors-are-symbols + var opt_colors_are_symbols = new OptionBool("Store colors as symbols (faster)", "--colors-are-symbols") + # --inline-coloring-numbers var opt_inline_coloring_numbers = new OptionBool("Inline colors and ids (semi-global)", "--inline-coloring-numbers") # --inline-some-methods @@ -50,7 +53,7 @@ redef class ToolContext 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_no_union_attribute) - self.option_context.add_option(self.opt_no_shortcut_equate) + self.option_context.add_option(self.opt_no_shortcut_equate, opt_colors_are_symbols) self.option_context.add_option(self.opt_inline_coloring_numbers, opt_inline_some_methods, opt_direct_call_monomorph, opt_skip_dead_methods, opt_semi_global) self.option_context.add_option(self.opt_colo_dead_methods) self.option_context.add_option(self.opt_tables_metrics) @@ -90,12 +93,55 @@ redef class ModelBuilder self.toolcontext.info("*** GENERATING C ***", 1) var compiler = new SeparateCompiler(mainmodule, self, runtime_type_analysis) + compiler.do_compilation + compiler.display_stats + + var time1 = get_time + self.toolcontext.info("*** END GENERATING C: {time1-time0} ***", 2) + write_and_make(compiler) + end + + # Count number of invocations by VFT + private var nb_invok_by_tables = 0 + # Count number of invocations by direct call + private var nb_invok_by_direct = 0 + # Count number of invocations by inlining + private var nb_invok_by_inline = 0 +end + +# Singleton that store the knowledge about the separate compilation process +class SeparateCompiler + super AbstractCompiler + + redef type VISITOR: SeparateCompilerVisitor + + # The result of the RTA (used to know live types and methods) + var runtime_type_analysis: nullable RapidTypeAnalysis + + private var undead_types: Set[MType] = new HashSet[MType] + private var live_unresolved_types: Map[MClassDef, Set[MType]] = new HashMap[MClassDef, HashSet[MType]] + + private var type_ids: Map[MType, Int] is noinit + private var type_colors: Map[MType, Int] is noinit + private var opentype_colors: Map[MType, Int] is noinit + protected var method_colors: Map[PropertyLayoutElement, Int] is noinit + protected var attr_colors: Map[MAttribute, Int] is noinit + + init do + var file = new_file("nit.common") + self.header = new CodeWriter(file) + self.compile_box_kinds + end + + redef fun do_compilation + do + var compiler = self compiler.compile_header var c_name = mainmodule.c_name # compile class structures - self.toolcontext.info("Property coloring", 2) + modelbuilder.toolcontext.info("Property coloring", 2) compiler.new_file("{c_name}.classes") compiler.do_property_coloring for m in mainmodule.in_importation.greaters do @@ -113,14 +159,22 @@ redef class ModelBuilder # compile methods for m in mainmodule.in_importation.greaters do - self.toolcontext.info("Generate C for module {m.full_name}", 2) + modelbuilder.toolcontext.info("Generate C for module {m.full_name}", 2) compiler.new_file("{m.c_name}.sep") compiler.compile_module_to_c(m) end # compile live & cast type structures - self.toolcontext.info("Type coloring", 2) + modelbuilder.toolcontext.info("Type coloring", 2) compiler.new_file("{c_name}.types") + compiler.compile_types + end + + # Color and compile type structures and cast information + fun compile_types + do + var compiler = self + var mtypes = compiler.do_type_coloring for t in mtypes do compiler.compile_type_to_c(t) @@ -131,43 +185,6 @@ redef class ModelBuilder compiler.compile_type_to_c(t) end - compiler.display_stats - - var time1 = get_time - self.toolcontext.info("*** END GENERATING C: {time1-time0} ***", 2) - write_and_make(compiler) - end - - # Count number of invocations by VFT - private var nb_invok_by_tables = 0 - # Count number of invocations by direct call - private var nb_invok_by_direct = 0 - # Count number of invocations by inlining - private var nb_invok_by_inline = 0 -end - -# Singleton that store the knowledge about the separate compilation process -class SeparateCompiler - super AbstractCompiler - - redef type VISITOR: SeparateCompilerVisitor - - # The result of the RTA (used to know live types and methods) - var runtime_type_analysis: nullable RapidTypeAnalysis - - private var undead_types: Set[MType] = new HashSet[MType] - private var live_unresolved_types: Map[MClassDef, Set[MType]] = new HashMap[MClassDef, HashSet[MType]] - - private var type_ids: Map[MType, Int] is noinit - private var type_colors: Map[MType, Int] is noinit - private var opentype_colors: Map[MType, Int] is noinit - protected var method_colors: Map[PropertyLayoutElement, Int] is noinit - protected var attr_colors: Map[MAttribute, Int] is noinit - - init do - var file = new_file("nit.common") - self.header = new CodeWriter(file) - self.compile_box_kinds end redef fun compile_header_structs do @@ -238,27 +255,21 @@ class SeparateCompiler fun compile_color_const(v: SeparateCompilerVisitor, m: Object, color: Int) do if color_consts_done.has(m) then return - if m isa MProperty then - if modelbuilder.toolcontext.opt_inline_coloring_numbers.value then - self.provide_declaration(m.const_color, "#define {m.const_color} {color}") - else - self.provide_declaration(m.const_color, "extern const int {m.const_color};") - v.add("const int {m.const_color} = {color};") - end - else if m isa MPropDef then + if m isa MEntity then if modelbuilder.toolcontext.opt_inline_coloring_numbers.value then self.provide_declaration(m.const_color, "#define {m.const_color} {color}") - else + else if not modelbuilder.toolcontext.opt_colors_are_symbols.value or not v.compiler.target_platform.supports_linker_script then self.provide_declaration(m.const_color, "extern const int {m.const_color};") v.add("const int {m.const_color} = {color};") - end - else if m isa MType then - if modelbuilder.toolcontext.opt_inline_coloring_numbers.value then - self.provide_declaration(m.const_color, "#define {m.const_color} {color}") else - self.provide_declaration(m.const_color, "extern const int {m.const_color};") - v.add("const int {m.const_color} = {color};") + # The color 'C' is the ``address'' of a false static variable 'XC' + self.provide_declaration(m.const_color, "#define {m.const_color} ((long)&X{m.const_color})\nextern const void X{m.const_color};") + if color == -1 then color = 0 # Symbols cannot be negative, so just use 0 for dead things + # Teach the linker that the address of 'XC' is `color`. + linker_script.add("X{m.const_color} = {color};") end + else + abort end color_consts_done.add(m) end @@ -1112,10 +1123,10 @@ class SeparateCompilerVisitor var res: nullable RuntimeVariable = null var recv = arguments.first var consider_null = not self.compiler.modelbuilder.toolcontext.opt_no_check_null.value or mmethod.name == "==" or mmethod.name == "!=" - var maybenull = recv.mcasttype isa MNullableType and consider_null + var maybenull = (recv.mcasttype isa MNullableType or recv.mcasttype isa MNullType) and consider_null if maybenull then self.add("if ({recv} == NULL) \{") - if mmethod.name == "==" then + if mmethod.name == "==" or mmethod.name == "is_same_instance" then res = self.new_var(bool_type) var arg = arguments[1] if arg.mcasttype isa MNullableType then @@ -1142,15 +1153,15 @@ class SeparateCompilerVisitor else self.add("\{") end - if not self.compiler.modelbuilder.toolcontext.opt_no_shortcut_equate.value and (mmethod.name == "==" or mmethod.name == "!=") then - if res == null then res = self.new_var(bool_type) - # Recv is not null, thus is arg is, it is easy to conclude (and respect the invariants) + if not self.compiler.modelbuilder.toolcontext.opt_no_shortcut_equate.value and (mmethod.name == "==" or mmethod.name == "!=" or mmethod.name == "is_same_instance") then + # Recv is not null, thus if arg is, it is easy to conclude (and respect the invariants) var arg = arguments[1] if arg.mcasttype isa MNullType then - if mmethod.name == "==" then - self.add("{res} = 0; /* arg is null but recv is not */") - else + if res == null then res = self.new_var(bool_type) + if mmethod.name == "!=" then self.add("{res} = 1; /* arg is null and recv is not */") + else # `==` and `is_same_instance` + self.add("{res} = 0; /* arg is null but recv is not */") end self.add("\}") # closes the null case self.add("if (0) \{") # what follow is useless, CC will drop it @@ -1939,20 +1950,18 @@ class VirtualRuntimeFunction redef fun call(v, arguments) do abort end -redef class MType - fun const_color: String do return "COLOR_{c_name}" +redef class MEntity + var const_color: String is lazy do return "COLOR_{c_name}" end interface PropertyLayoutElement end redef class MProperty super PropertyLayoutElement - fun const_color: String do return "COLOR_{c_name}" end redef class MPropDef super PropertyLayoutElement - fun const_color: String do return "COLOR_{c_name}" end redef class AMethPropdef