fn jit_compilation_started()

in src/profiler/elastic_apm_profiler/src/profiler/mod.rs [1112:1259]


    fn jit_compilation_started(
        &self,
        function_id: FunctionID,
        is_safe_to_block: BOOL,
    ) -> Result<(), HRESULT> {
        if !IS_ATTACHED.load(Ordering::SeqCst) || is_safe_to_block == 0 {
            return Ok(());
        }

        let modules = self.modules.lock().unwrap();

        if !IS_ATTACHED.load(Ordering::SeqCst) {
            return Ok(());
        }

        let profiler_borrow = self.profiler_info.borrow();
        let profiler_info = profiler_borrow.as_ref().unwrap();
        let function_info = profiler_info.get_function_info(function_id).map_err(|e| {
            log::warn!(
                "JITCompilationStarted: get function info failed for {}",
                function_id
            );
            e
        })?;

        let module_metadata = modules.get(&function_info.module_id);
        if module_metadata.is_none() {
            return Ok(());
        }

        let module_metadata = module_metadata.unwrap();
        let call_target_enabled = *env::ELASTIC_APM_PROFILER_CALLTARGET_ENABLED;
        let loader_injected_in_app_domain = {
            // scope reading to this block
            self.first_jit_compilation_app_domains
                .read()
                .unwrap()
                .contains(&module_metadata.app_domain_id)
        };

        // TODO investigate logging ONLY on MAIN() if MANAGED_PROFILER_LOADED is false

        // TODO add MANAGED_PROFILER_LOADED and add same check for Elastic.Apm.dll
        if call_target_enabled && loader_injected_in_app_domain {
            return Ok(());
        }

        let caller = module_metadata
            .import
            .get_function_info(function_info.token)?;

        log::trace!(
            "JITCompilationStarted: function_id={}, name={}()",
            function_id,
            caller.full_name()
        );

        let is_desktop_iis = self.is_desktop_iis.load(Ordering::SeqCst);
        let valid_startup_hook_callsite = if is_desktop_iis {
            match &caller.type_info {
                Some(t) => {
                    &module_metadata.assembly_name == "System.Web"
                        && t.name == "System.Web.Compilation.BuildManager"
                        && &caller.name == "InvokePreStartInitMethods"
                }
                None => false,
            }
        } else {
            !(&module_metadata.assembly_name == "System"
                || &module_metadata.assembly_name == "System.Net.Http")
        };

        if valid_startup_hook_callsite && !loader_injected_in_app_domain {
            let runtime_info_borrow = self.runtime_info.borrow();
            let runtime_info = runtime_info_borrow.as_ref().unwrap();

            let domain_neutral_assembly = runtime_info.is_desktop_clr()
                && self.cor_lib_module_loaded.load(Ordering::SeqCst)
                && self.cor_app_domain_id.load(Ordering::SeqCst) == module_metadata.app_domain_id;

            log::info!(
                "JITCompilationStarted: Startup hook registered in function_id={} token={} \
                name={}() assembly_name={} app_domain_id={} domain_neutral={}",
                function_id,
                &function_info.token,
                &caller.full_name(),
                &module_metadata.assembly_name,
                &module_metadata.app_domain_id,
                domain_neutral_assembly
            );

            self.first_jit_compilation_app_domains
                .write()
                .unwrap()
                .insert(module_metadata.app_domain_id);

            startup_hook::run_il_startup_hook(
                profiler_info,
                &module_metadata,
                function_info.module_id,
                function_info.token,
            )?;

            if is_desktop_iis {
                // TODO: hookup IIS module
            }
        }

        if !call_target_enabled {
            if &module_metadata.assembly_name == "Microsoft.AspNetCore.Hosting" {
                return Ok(());
            }

            let method_replacements = module_metadata.get_method_replacements_for_caller(&caller);
            if method_replacements.is_empty() {
                return Ok(());
            }

            let mut module_wrapper_tokens = self.module_wrapper_tokens.lock().unwrap();
            let mut module_wrapper_token = module_wrapper_tokens
                .get_mut(&function_info.module_id)
                .unwrap();

            process::process_insertion_calls(
                profiler_info,
                &module_metadata,
                &mut module_wrapper_token,
                function_id,
                function_info.module_id,
                function_info.token,
                &caller,
                &method_replacements,
            )?;

            process::process_replacement_calls(
                profiler_info,
                &module_metadata,
                &mut module_wrapper_token,
                function_id,
                function_info.module_id,
                function_info.token,
                &caller,
                &method_replacements,
            )?;
        }

        Ok(())
    }