Instantiate a new routine pointer

Property definitions

nitc $ AbstractCompilerVisitor :: routine_ref_instance
	# Instantiate a new routine pointer
	fun routine_ref_instance(routine_mclass_type: MClassType, recv: RuntimeVariable, callsite: CallSite): RuntimeVariable is abstract
src/compiler/abstract_compiler.nit:1371,2--1372,130

nitc $ SeparateCompilerVisitor :: routine_ref_instance
	redef fun routine_ref_instance(routine_type, recv, callsite)
	do
		#debug "ENTER ref_instance"
		var mmethoddef = callsite.mpropdef
		var mmethod = mmethoddef.mproperty
		# routine_mclass is the specialized one, e.g: FunRef1, ProcRef2, etc..
		var routine_mclass = routine_type.mclass

		var nclasses = mmodule.model.get_mclasses_by_name("RoutineRef").as(not null)
		var base_routine_mclass = nclasses.first

		# All routine classes use the same `NEW` constructor.
		# However, they have different declared `class` and `type` value.
		self.require_declaration("NEW_{base_routine_mclass.c_name}")

		var recv_class_cname = recv.mcasttype.as(MClassType).mclass.c_name
		var my_recv = recv

		if recv.mtype.is_c_primitive then
			my_recv = autobox(recv, mmodule.object_type)
		end
		var my_recv_mclass_type = my_recv.mtype.as(MClassType)

		# The class of the concrete Routine must exist (e.g ProcRef0, FunRef0, etc.)
		self.require_declaration("class_{routine_mclass.c_name}")
		self.require_declaration(mmethoddef.c_name)

		var thunk_function = mmethoddef.callref_thunk(my_recv_mclass_type)
		# If the receiver is exact, then there's no need to make a
		# polymorph call to the underlying method.
		thunk_function.polymorph_call_flag = not my_recv.is_exact
		var runtime_function = mmethoddef.virtual_runtime_function

		var is_c_equiv = runtime_function.msignature.c_equiv(thunk_function.msignature)

		var c_ref = thunk_function.c_ref
		if is_c_equiv then
			var const_color = mmethoddef.mproperty.const_color
			c_ref = "{class_info(my_recv)}->vft[{const_color}]"
			self.require_declaration(const_color)
		else
			self.require_declaration(thunk_function.c_name)
			compiler.thunk_todo(thunk_function)
		end
		var res: RuntimeVariable
		if routine_type.need_anchor then
			hardening_live_open_type(routine_type)
			link_unresolved_type(self.frame.mpropdef.mclassdef, routine_type)
			var recv2 = self.frame.arguments.first
			var recv2_type_info = self.type_info(recv2)
			self.require_declaration(routine_type.const_color)
			res = self.new_expr("NEW_{base_routine_mclass.c_name}({my_recv}, (nitmethod_t){c_ref}, &class_{routine_mclass.c_name}, {recv2_type_info}->resolution_table->types[{routine_type.const_color}])", routine_type)
		else
			self.require_declaration("type_{routine_type.c_name}")
			compiler.undead_types.add(routine_type)
			res = self.new_expr("NEW_{base_routine_mclass.c_name}({my_recv}, (nitmethod_t){c_ref}, &class_{routine_mclass.c_name}, &type_{routine_type.c_name})", routine_type)
		end
		return res
	end
src/compiler/separate_compiler.nit:2233,2--2291,4

nitc $ GlobalCompilerVisitor :: routine_ref_instance
        redef fun routine_ref_instance(routine_mclass_type, recv, callsite)
        do
		var mmethoddef = callsite.mpropdef
                var method = new CustomizedRuntimeFunction(mmethoddef, recv.mcasttype.as(MClassType))
                var my_recv = recv
                if recv.mtype.is_c_primitive then
                        var object_type = mmodule.object_type
                        my_recv = autobox(recv, object_type)
                end
                var thunk = new CustomizedThunkFunction(mmethoddef, my_recv.mtype.as(MClassType))
                thunk.polymorph_call_flag = not my_recv.is_exact
                compiler.todo(method)
                compiler.todo(thunk)
		var ret_type = self.anchor(routine_mclass_type).as(MClassType)
                var res = self.new_expr("NEW_{ret_type.c_name}({my_recv}, &{thunk.c_name})", ret_type)
                return res
        end
src/compiler/global_compiler.nit:466,9--482,11

nitc $ SeparateErasureCompilerVisitor :: routine_ref_instance
        redef fun routine_ref_instance(routine_type, recv, callsite)
        do
		var mmethoddef = callsite.mpropdef
                #debug "ENTER ref_instance"
                var mmethod = mmethoddef.mproperty
                # routine_mclass is the specialized one, e.g: FunRef1, ProcRef2, etc..
                var routine_mclass = routine_type.mclass

                var nclasses = mmodule.model.get_mclasses_by_name("RoutineRef").as(not null)
                var base_routine_mclass = nclasses.first

                # All routine classes use the same `NEW` constructor.
                # However, they have different declared `class` and `type` value.
                self.require_declaration("NEW_{base_routine_mclass.c_name}")

                var recv_class_cname = recv.mcasttype.as(MClassType).mclass.c_name
                var my_recv = recv

                if recv.mtype.is_c_primitive then
                        my_recv = autobox(recv, mmodule.object_type)
                end
                var my_recv_mclass_type = my_recv.mtype.as(MClassType)

                # The class of the concrete Routine must exist (e.g ProcRef0, FunRef0, etc.)
                self.require_declaration("class_{routine_mclass.c_name}")

                self.require_declaration(mmethoddef.c_name)

                var thunk_function = mmethoddef.callref_thunk(my_recv_mclass_type)
                var runtime_function = mmethoddef.virtual_runtime_function

                var is_c_equiv = runtime_function.msignature.c_equiv(thunk_function.msignature)

                var c_ref = thunk_function.c_ref
                if is_c_equiv then
                        var const_color = mmethoddef.mproperty.const_color
                        c_ref = "{class_info(my_recv)}->vft[{const_color}]"
                        self.require_declaration(const_color)
                else
                        self.require_declaration(thunk_function.c_name)
                        compiler.thunk_todo(thunk_function)
                end
                compiler.thunk_todo(thunk_function)

                # Each RoutineRef points to a receiver AND a callref_thunk
                var res = self.new_expr("NEW_{base_routine_mclass.c_name}({my_recv}, (nitmethod_t){c_ref}, &class_{routine_mclass.c_name})", routine_type)
                #debug "LEAVING ref_instance"
                return res

        end
src/compiler/separate_erasure_compiler.nit:723,9--772,11