var opt_inline_some_methods = new OptionBool("Allow the separate compiler to inline some methods (semi-global)", "--inline-some-methods")
# --direct-call-monomorph
var opt_direct_call_monomorph = new OptionBool("Allow the separate compiler to direct call monomorph sites (semi-global)", "--direct-call-monomorph")
+ # --direct-call-monomorph0
+ var opt_direct_call_monomorph0 = new OptionBool("Allow the separate compiler to direct call monomorph sites (semi-global)", "--direct-call-monomorph0")
# --skip-dead-methods
var opt_skip_dead_methods = new OptionBool("Do not compile dead methods (semi-global)", "--skip-dead-methods")
# --semi-global
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(opt_colors_are_symbols, opt_trampoline_call, opt_guard_call, opt_substitute_monomorph, opt_link_boost)
+ self.option_context.add_option(opt_colors_are_symbols, opt_trampoline_call, opt_guard_call, opt_direct_call_monomorph0, 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)
redef fun compile_callsite(callsite, args)
do
var rta = compiler.runtime_type_analysis
- var mmethod = callsite.mproperty
# TODO: Inlining of new-style constructors with initializers
if compiler.modelbuilder.toolcontext.opt_direct_call_monomorph.value and rta != null and callsite.mpropdef.initializers.is_empty then
var tgs = rta.live_targets(callsite)
if tgs.length == 1 then
- # DIRECT CALL
- var res0 = before_send(mmethod, args)
- var res = call(tgs.first, tgs.first.mclassdef.bound_mtype, args)
- if res0 != null then
- assert res != null
- self.assign(res0, res)
- res = res0
- end
- add("\}") # close the before_send
- return res
+ return direct_call(tgs.first, args)
end
end
+ # Shortcut intern methods as they are not usually redefinable
+ if callsite.mpropdef.is_intern and callsite.mproperty.name != "object_id" then
+ # `object_id` is the only redefined intern method, so it can not be directly called.
+ # TODO find a less ugly approach?
+ return direct_call(callsite.mpropdef, args)
+ end
return super
end
+
+ # Fully and directly call a mpropdef
+ #
+ # This method is used by `compile_callsite`
+ private fun direct_call(mpropdef: MMethodDef, args: Array[RuntimeVariable]): nullable RuntimeVariable
+ do
+ var res0 = before_send(mpropdef.mproperty, args)
+ var res = call(mpropdef, mpropdef.mclassdef.bound_mtype, args)
+ if res0 != null then
+ assert res != null
+ self.assign(res0, res)
+ res = res0
+ end
+ add("\}") # close the before_send
+ return res
+ end
redef fun send(mmethod, arguments)
do
if arguments.first.mcasttype.ctype != "val*" then
else
ress = ""
end
- if mentity isa MMethod and compiler.modelbuilder.toolcontext.opt_guard_call.value then
+ if mentity isa MMethod and compiler.modelbuilder.toolcontext.opt_direct_call_monomorph0.value then
+ # opt_direct_call_monomorph0 is used to compare the efficiency of the alternative lookup implementation, ceteris paribus.
+ # The difference with the non-zero option is that the monomorphism is looked-at on the mmethod level and not at the callsite level.
+ # TODO: remove this mess and use per callsite service to detect monomorphism in a single place.
+ var md = compiler.is_monomorphic(mentity)
+ if md != null then
+ var callsym = md.virtual_runtime_function.c_name
+ self.require_declaration(callsym)
+ self.add "{ress}{callsym}({ss}); /* {mmethod} on {arguments.first.inspect}*/"
+ else
+ self.require_declaration(const_color)
+ self.add "{ress}(({runtime_function.c_funptrtype})({arguments.first}->class->vft[{const_color}]))({ss}); /* {mmethod} on {arguments.first.inspect}*/"
+ end
+ else if mentity isa MMethod and compiler.modelbuilder.toolcontext.opt_guard_call.value then
var callsym = "CALL_" + const_color
self.require_declaration(callsym)
self.add "if (!{callsym}) \{"
var nclass = self.get_class("NativeArray")
var recv = "((struct instance_{nclass.c_name}*){arguments[0]})->values"
if pname == "[]" then
- self.ret(self.new_expr("{recv}[{arguments[1]}]", ret_type.as(not null)))
+ # Because the objects are boxed, return the box to avoid unnecessary (or broken) unboxing/reboxing
+ var res = self.new_expr("{recv}[{arguments[1]}]", compiler.mainmodule.object_type)
+ res.mcasttype = ret_type.as(not null)
+ self.ret(res)
return
else if pname == "[]=" then
self.add("{recv}[{arguments[1]}]={arguments[2]};")