private fun table_send(mmethod: MMethod, arguments: Array[RuntimeVariable], mentity: MEntity): nullable RuntimeVariable
do
compiler.modelbuilder.nb_invok_by_tables += 1
if compiler.modelbuilder.toolcontext.opt_invocation_metrics.value then add("count_invoke_by_tables++;")
assert arguments.length == mmethod.intro.msignature.arity + 1 else debug("Invalid arity for {mmethod}. {arguments.length} arguments given.")
var res0 = before_send(mmethod, arguments)
var runtime_function = mmethod.intro.virtual_runtime_function
var msignature = runtime_function.called_signature
adapt_signature(mmethod.intro, arguments)
var res: nullable RuntimeVariable
var ret = msignature.return_mtype
if ret == null then
res = null
else
res = self.new_var(ret)
end
var ss = arguments.join(", ")
var const_color = mentity.const_color
var ress
if res != null then
ress = "{res} = "
else
ress = ""
end
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})({class_info(arguments.first)}->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}) \{"
self.require_declaration(const_color)
self.add "{ress}(({runtime_function.c_funptrtype})({class_info(arguments.first)}->vft[{const_color}]))({ss}); /* {mmethod} on {arguments.first.inspect}*/"
self.add "\} else \{"
self.add "{ress}{callsym}({ss}); /* {mmethod} on {arguments.first.inspect}*/"
self.add "\}"
else if mentity isa MMethod and compiler.modelbuilder.toolcontext.opt_trampoline_call.value then
var callsym = "CALL_" + const_color
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})({class_info(arguments.first)}->vft[{const_color}]))({ss}); /* {mmethod} on {arguments.first.inspect}*/"
end
if res0 != null then
assert res != null
assign(res0,res)
res = res0
end
self.add("\}") # closes the null case
return res
end
src/compiler/separate_compiler.nit:1539,2--1610,4