in src/profiler/elastic_apm_profiler/src/profiler/mod.rs [1513:1681]
fn calltarget_request_rejit_for_module(
&self,
module_id: ModuleID,
module_metadata: &ModuleMetadata,
) -> Result<usize, HRESULT> {
let metadata_import = &module_metadata.import;
let assembly_metadata: AssemblyMetaData =
module_metadata.assembly_import.get_assembly_metadata()?;
let mut method_ids = vec![];
for integration in &module_metadata.integrations {
let target = match integration.method_replacement.target() {
Some(t)
if t.is_valid_for_assembly(
&module_metadata.assembly_name,
&assembly_metadata.version,
) =>
{
t
}
_ => continue,
};
let wrapper = match integration.method_replacement.wrapper() {
Some(w) if w.action == WrapperMethodAction::CallTargetModification => w,
_ => continue,
};
let type_def = match helpers::find_type_def_by_name(
target.type_name(),
&module_metadata.assembly_name,
&metadata_import,
) {
Some(t) => t,
None => continue,
};
let method_defs =
metadata_import.enum_methods_with_name(type_def, target.method_name())?;
let mut rejit_target_found = false;
for method_def in method_defs {
let caller: FunctionInfo = match metadata_import.get_function_info(method_def) {
Ok(c) => c,
Err(e) => {
log::warn!(
"Could not get function_info for method_def={}, {}",
method_def,
e
);
continue;
}
};
let parsed_signature = match caller.method_signature.try_parse() {
Some(p) => p,
None => {
log::warn!(
"The method {} with signature={:?} cannot be parsed",
&caller.full_name(),
&caller.method_signature.data
);
continue;
}
};
let signature_types = match target.signature_types() {
Some(s) => s,
None => {
log::debug!("target does not have arguments defined");
continue;
}
};
if parsed_signature.arg_len as usize != signature_types.len() - 1 {
log::debug!(
"The caller for method_def {} expected {} arguments while integration has {}",
target.method_name(),
parsed_signature.arg_len as usize,
signature_types.len() - 1
);
continue;
}
log::trace!(
"comparing signature for method {}.{}",
target.type_name(),
target.method_name()
);
let mut mismatch = false;
for arg_idx in 0..parsed_signature.arg_len {
let (start_idx, _) = parsed_signature.args[arg_idx as usize];
let (argument_type_name, _) = get_sig_type_token_name(
&parsed_signature.data[start_idx..],
&metadata_import,
);
let integration_argument_type_name = &signature_types[arg_idx as usize + 1];
log::trace!(
"-> {} = {}",
&argument_type_name,
integration_argument_type_name
);
if &argument_type_name != integration_argument_type_name
&& integration_argument_type_name != IGNORE
{
mismatch = true;
break;
}
}
if mismatch {
log::debug!(
"The caller for method_def {} does not have the right type of arguments",
target.method_name()
);
continue;
}
rejit_target_found = true;
let mut borrow = self.rejit_handler.borrow_mut();
let rejit_handler: &mut RejitHandler = borrow.as_mut().unwrap();
let rejit_module = rejit_handler.get_or_add_module(module_id);
let rejit_method = rejit_module.get_or_add_method(method_def);
rejit_method.set_function_info(caller);
rejit_method.set_method_replacement(integration.method_replacement.clone());
method_ids.push(method_def);
if log::log_enabled!(Level::Info) {
let caller_assembly_is_domain_neutral = IS_DESKTOP_CLR.load(Ordering::SeqCst)
&& self.cor_lib_module_loaded.load(Ordering::SeqCst)
&& module_metadata.app_domain_id
== self.cor_app_domain_id.load(Ordering::SeqCst);
let caller = rejit_method.function_info().unwrap();
log::info!(
"enqueue for ReJIT module_id={}, method_def={}, app_domain_id={}, \
domain_neutral={}, assembly={}, type={}, method={}, signature={:?}",
module_id,
method_def,
module_metadata.app_domain_id,
caller_assembly_is_domain_neutral,
&module_metadata.assembly_name,
caller.type_info.as_ref().map_or("", |t| t.name.as_str()),
&caller.name,
&caller.signature.bytes()
);
}
}
if !rejit_target_found {
log::error!(
"No rejit method found for target: {}.{}",
target.type_name(),
target.method_name()
)
}
}
let len = method_ids.len();
if !method_ids.is_empty() {
let borrow = self.rejit_handler.borrow();
let rejit_handler = borrow.as_ref().unwrap();
rejit_handler.enqueue_for_rejit(vec![module_id; method_ids.len()], method_ids);
}
Ok(len)
}