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")
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)
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)
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
# 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
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