X-Git-Url: http://nitlanguage.org diff --git a/src/compiler/separate_compiler.nit b/src/compiler/separate_compiler.nit index b14da6a..9273c45 100644 --- a/src/compiler/separate_compiler.nit +++ b/src/compiler/separate_compiler.nit @@ -29,12 +29,15 @@ 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") + var opt_colors_are_symbols = new OptionBool("Store colors as symbols (link-boost)", "--colors-are-symbols") # --trampoline-call var opt_trampoline_call = new OptionBool("Use an indirection when calling", "--trampoline-call") # --substitute-monomorph - var opt_substitute_monomorph = new OptionBool("Replace monomorph trampoline with direct call", "--substitute-monomorph") + var opt_substitute_monomorph = new OptionBool("Replace monomorph trampoline with direct call (link-boost)", "--substitute-monomorph") + # --link-boost + var opt_link_boost = new OptionBool("Enable all link-boost optimizations", "--link-boost") # --inline-coloring-numbers var opt_inline_coloring_numbers = new OptionBool("Inline colors and ids (semi-global)", "--inline-coloring-numbers") @@ -57,7 +60,8 @@ 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, opt_colors_are_symbols, opt_trampoline_call, opt_substitute_monomorph) + self.option_context.add_option(self.opt_no_shortcut_equate) + self.option_context.add_option(opt_colors_are_symbols, opt_trampoline_call, opt_substitute_monomorph, opt_link_boost) 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) @@ -74,6 +78,13 @@ redef class ToolContext tc.opt_direct_call_monomorph.value = true tc.opt_skip_dead_methods.value = true end + if tc.opt_link_boost.value then + tc.opt_colors_are_symbols.value = true + tc.opt_substitute_monomorph.value = true + end + if tc.opt_substitute_monomorph.value then + tc.opt_trampoline_call.value = true + end end var separate_compiler_phase = new SeparateCompilerPhase(self, null) @@ -160,6 +171,7 @@ class SeparateCompiler compiler.compile_nitni_global_ref_functions compiler.compile_main_function compiler.compile_finalizer_function + compiler.link_mmethods # compile methods for m in mainmodule.in_importation.greaters do @@ -569,30 +581,65 @@ class SeparateCompiler # Generate trampolines if modelbuilder.toolcontext.opt_trampoline_call.value then r2.compile_trampolines(self) - - # Replace monomorphic call to a trampoline by a direct call to the virtual implementation - if modelbuilder.toolcontext.opt_substitute_monomorph.value then do - var m = pd.mproperty - if rta == null then - # Without RTA, monomorphic means alone (uniq name) - if m.mpropdefs.length != 1 then break label - else - # With RTA, monomorphic means only live methoddef - if not rta.live_methoddefs.has(pd) then break label - for md in m.mpropdefs do - if md != pd and rta.live_methoddefs.has(md) then break label - end - end - # Here the trick, GNU ld can substitute symbols with specific values. - var n2 = "CALL_" + m.const_color - linker_script.add("{n2} = {r2.c_name};") - end label end end end self.mainmodule = old_module end + # Process all introduced methods and compile some linking information (if needed) + fun link_mmethods + do + if not modelbuilder.toolcontext.opt_substitute_monomorph.value then return + + for mmodule in mainmodule.in_importation.greaters do + for cd in mmodule.mclassdefs do + for m in cd.intro_mproperties do + if not m isa MMethod then continue + link_mmethod(m) + end + end + end + end + + # Compile some linking information (if needed) + fun link_mmethod(m: MMethod) + do + var n2 = "CALL_" + m.const_color + + # Replace monomorphic call by a direct call to the virtual implementation + var md = is_monomorphic(m) + if md != null then + linker_script.add("{n2} = {md.virtual_runtime_function.c_name};") + end + + end + + # The single mmethodef called in case of monomorphism. + # Returns nul if dead or polymorphic. + fun is_monomorphic(m: MMethod): nullable MMethodDef + do + var rta = runtime_type_analysis + if rta == null then + # Without RTA, monomorphic means alone (uniq name) + if m.mpropdefs.length == 1 then + return m.mpropdefs.first + else + return null + end + else + # With RTA, monomorphic means only live methoddef + var res: nullable MMethodDef = null + for md in m.mpropdefs do + if rta.live_methoddefs.has(md) then + if res != null then return null + res = md + end + end + return res + end + end + # Globaly compile the type structure of a live type fun compile_type_to_c(mtype: MType) do @@ -1985,6 +2032,9 @@ class SeparateRuntimeFunction compiler.names[self.c_name] = "{mmethoddef.full_name} ({mmethoddef.location.file.filename}:{mmethoddef.location.line_start})" end + # Compile the trampolines used to implement late-binding. + # + # See `opt_trampoline_call`. fun compile_trampolines(compiler: SeparateCompiler) do var recv = self.mmethoddef.mclassdef.bound_mtype