From af553b57edd36e807f56e1eafa6046acb1af0364 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Tue, 15 Nov 2016 12:51:54 -0500 Subject: [PATCH] [jit] Optimize out the early pinvoke address loading done by emit_native_wrapper () when coop+direct pinvokes is enabled, since its not needed, and it generates MONO_PATCH_INFO_ICALL_ADDR relocations which cause pinvoke lookups at runtime on platforms where its not supported like watchos. Fixes #45369. (#3960) --- mono/mini/aot-compiler.c | 2 ++ mono/mini/method-to-ir.c | 12 +++++++++++- mono/mini/mini.c | 1 + mono/mini/mini.h | 5 ++++- 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c index 08ce2f06701..6c30c8f5bd1 100644 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@ -7527,6 +7527,8 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method) flags = (JitFlags)(flags | JIT_FLAG_LLVM_ONLY | JIT_FLAG_EXPLICIT_NULL_CHECKS); if (acfg->aot_opts.no_direct_calls) flags = (JitFlags)(flags | JIT_FLAG_NO_DIRECT_ICALLS); + if (acfg->aot_opts.direct_pinvoke) + flags = (JitFlags)(flags | JIT_FLAG_DIRECT_PINVOKE); jit_timer = mono_time_track_start (); cfg = mini_method_compile (method, acfg->opts, mono_get_root_domain (), flags, 0, index); diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index ee0535ec252..de0e58ab179 100644 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -12579,7 +12579,17 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b cmethod = (MonoMethod *)mono_method_get_wrapper_data (method, token); if (cfg->compile_aot) { - EMIT_NEW_AOTCONST (cfg, ins, MONO_PATCH_INFO_ICALL_ADDR, cmethod); + if (cfg->direct_pinvoke && ip + 6 < end && (ip [6] == CEE_POP)) { + /* + * This is generated by emit_native_wrapper () to resolve the pinvoke address + * before the call, its not needed when using direct pinvoke. + * This is not an optimization, but its used to avoid looking up pinvokes + * on platforms which don't support dlopen (). + */ + EMIT_NEW_PCONST (cfg, ins, NULL); + } else { + EMIT_NEW_AOTCONST (cfg, ins, MONO_PATCH_INFO_ICALL_ADDR, cmethod); + } } else { ptr = mono_lookup_internal_call (cmethod); g_assert (ptr); diff --git a/mono/mini/mini.c b/mono/mini/mini.c index e94e9fc18c0..5b42ca510f3 100644 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -3315,6 +3315,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl cfg->soft_breakpoints = debug_options.soft_breakpoints; cfg->check_pinvoke_callconv = debug_options.check_pinvoke_callconv; cfg->disable_direct_icalls = disable_direct_icalls; + cfg->direct_pinvoke = (flags & JIT_FLAG_DIRECT_PINVOKE) != 0; if (try_generic_shared) cfg->gshared = TRUE; cfg->compile_llvm = try_llvm; diff --git a/mono/mini/mini.h b/mono/mini/mini.h index 1d4184ee09c..9e6f8f7523f 100644 --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -1513,12 +1513,14 @@ typedef enum { JIT_FLAG_FULL_AOT = (1 << 2), /* Whenever to compile with LLVM */ JIT_FLAG_LLVM = (1 << 3), - /* Whenever to disable direct calls to direct calls to icall functions */ + /* Whenever to disable direct calls to icall functions */ JIT_FLAG_NO_DIRECT_ICALLS = (1 << 4), /* Emit explicit null checks */ JIT_FLAG_EXPLICIT_NULL_CHECKS = (1 << 5), /* Whenever to compile in llvm-only mode */ JIT_FLAG_LLVM_ONLY = (1 << 6), + /* Whenever calls to pinvoke functions are made directly */ + JIT_FLAG_DIRECT_PINVOKE = (1 << 7) } JitFlags; /* Bit-fields in the MonoBasicBlock.region */ @@ -1688,6 +1690,7 @@ typedef struct { guint disable_out_of_line_bblocks : 1; guint disable_direct_icalls : 1; guint disable_gc_safe_points : 1; + guint direct_pinvoke : 1; guint create_lmf_var : 1; /* * When this is set, the code to push/pop the LMF from the LMF stack is generated as IR -- 2.25.1