Property definitions

nitc $ SeparateCompilerVisitor :: table_send
	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