-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[DRAFT][mono][aot] Implementation of nollvm init method #89074
Conversation
Signed-off-by: Vlad - Alexandru Ionescu <[email protected]>
Signed-off-by: Vlad - Alexandru Ionescu <[email protected]>
Signed-off-by: Vlad - Alexandru Ionescu <[email protected]>
Signed-off-by: Vlad - Alexandru Ionescu <[email protected]>
Signed-off-by: Vlad - Alexandru Ionescu <[email protected]>
Signed-off-by: Vlad - Alexandru Ionescu <[email protected]>
Signed-off-by: Vlad - Alexandru Ionescu <[email protected]>
@vargaz @lambdageek This is ready for review, I've enabled the optimization just to see how it behaves on CI. |
Signed-off-by: Vlad - Alexandru Ionescu <[email protected]>
mono_bitset_set (inited_bitset, method_index); | ||
} | ||
} | ||
mono_error_assert_ok (error); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vargaz do we want to propagate this error?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I completely followed what is going on. but the marshal stuff looks ok. I had some minor suggestions for method-to-ir and the arm64 backend. And a question about why this is backend-specific.
src/mono/mono/mini/method-to-ir.c
Outdated
case MONO_CEE_AOT_MODULE: { | ||
if (cfg->compile_aot) { | ||
EMIT_NEW_AOTCONST (cfg, ins, MONO_PATCH_INFO_AOT_MODULE, NULL); | ||
*sp++ = ins; | ||
} | ||
break; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't expect to see this opcode if we're JITing, right? can we do g_assert (cfg->compile_aot)
?
Alternately, can we add an else
case that pushes some dummy constant (NULL?) on the stack. That way even if we emit this during JITing by accident it will just mean we'll see a NULL module in the icall instead of getting a messed up operand stack in the wrapper method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I'll go with the first approach, since the second will also need a NULL check for the amodule inside the call.
src/mono/mono/mini/mini-arm64.c
Outdated
emit_call (MonoCompile *cfg, guint8* code, MonoJumpInfoType patch_type, gconstpointer data, MonoMethod *method) | ||
{ | ||
/* | ||
mono_add_patch_info_rel (cfg, code - cfg->native_code, patch_type, data, MONO_R_ARM64_IMM); | ||
code = emit_imm64_template (code, ARMREG_LR); | ||
arm_blrx (code, ARMREG_LR); | ||
*/ | ||
mono_add_patch_info_rel (cfg, code - cfg->native_code, patch_type, data, MONO_R_ARM64_BL); | ||
mono_add_patch_info_rel (cfg, code - cfg->native_code, patch_type, method ? method : data, MONO_R_ARM64_BL); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems unnecessary - MonoMethod*
is a pointer-sized value. You can just pass it in for the data
argument (possibly with a cast to deal with the const-ness).
/* | ||
* Methods init bitset used for initialization during the runtime | ||
*/ | ||
amodule->mono_inited = mono_bitset_new (amodule->info.nmethods, 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As we discussed offline, would be good to think of memory leaks. Is it allocated within the mempool?
The main idea is to have this |
got it. thanks. are we planning to use this by default? or only if we enable some direct call aot option? This is introducing slow overhead on every method call, right? If I call For a follow-up PR, is there some way we can emit an inlined check of the bitmask? so that in the fast path we're just doing a memory load and avoiding a call from the prolog of every method? |
So this is an experiment to see whenever this can be made to work and what the perf impact woudl be. In theory, it can be made as fast as the llvm version, which does: The upside is that these methods can now be called directly, the caller doesn't have to go through a PLT entry. So the method becomes a little slower, but calling it becomes a little cheaper. |
Signed-off-by: Vlad - Alexandru Ionescu <[email protected]>
Signed-off-by: Vlad - Alexandru Ionescu <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good. I'm not sure about ENABLE_LLVM
- that just means whether the AOT compiler has LLVM support built-in - not that the LLVM support is being used for the current compilation - so I'm not sure that's the condition for deciding what does into the wrapper method.
src/mono/mono/mini/aot-runtime.c
Outdated
#ifdef ENABLE_WIP_METHOD_NOLLVM_SELF_INIT | ||
else | ||
mono_bitset_set (mono_aot_get_mono_inited(amodule), method_index); | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you used to have an arm64 target check here (and also that LLVM was disabled). but now you don't.
Do you need to enable ENABLE_WIP_METHOD_NOLLVM_SELF_INIT
in src/mono/CMakeLists.txt
if we're targeting arm64?
src/mono/mono/metadata/marshal.c
Outdated
#ifndef ENABLE_LLVM | ||
get_marshal_cb ()->emit_method_init (mb); | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't make sense to me. ENABLE_LLVM
just means we're building the runtime with LLVM support. It doesn't mean that we're using LLVM for the current AOT compilation. I think you need two different wrapper subtypes AOT_INIT_METHOD_LLVM
and AOT_INIT_METHOD_NOLLVM
and at the callsite you would do something like mono_marshal_get_aot_init_wrapper (cfg->compile_aot && COMPILE_LLVM(cfg) ? AOT_INIT_METHOD_LLVM : AOT_INIT_METHOD_NOLLVM)
Signed-off-by: Vlad - Alexandru Ionescu <[email protected]>
Co-authored-by: Aleksey Kliger (λgeek) <[email protected]>
Signed-off-by: Vlad <[email protected]>
Converting this PR to draft in order to test experimental changes on arm64.
|
#ifdef ENABLE_WIP_METHOD_NOLLVM_SELF_INIT | ||
if (cfg->compile_aot && !COMPILE_LLVM (cfg)) { | ||
code = emit_imm (code, ARMREG_R0, cfg->method_index); | ||
code = emit_call (cfg, code, MONO_PATCH_INFO_METHOD, (gconstpointer) mono_marshal_get_aot_init_wrapper (AOT_INIT_METHOD)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure if this is a correct way to invoke wrappers generated in:
runtime/src/mono/mono/mini/aot-compiler.c
Line 4470 in 6229f5f
add_method (acfg, mono_marshal_get_aot_init_wrapper ((MonoAotInitSubtype)i)); |
During the native linking, there is an undefined symbols for architecture arm64:
"_mono_aot_HelloWorld_init_method", referenced from:
HelloWorld_Program_Main_string__ in mono_aot_0nLeOF.o
HelloWorld_Program__ctor in mono_aot_0nLeOF.o
wrapper_other_object_init_method_intptr_intptr in mono_aot_0nLeOF.o
wrapper_other_object_init_method_gshared_mrgctx_intptr_intptr_intptr in mono_aot_0nLeOF.o
wrapper_other_object_init_method_gshared_this_intptr_intptr_intptr in mono_aot_0nLeOF.o
wrapper_other_object_init_method_gshared_vtable_intptr_intptr_intptr in mono_aot_0nLeOF.o
I think it comes from method prolog trying to invoke the init wrapper, but I would expect invocation of wrapper_other_object_init_method_intptr_intptr
instead of _mono_aot_HelloWorld_init_method
. @vargaz What we are doing wrong?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW, I am not 100% how this should work but I think the body of _mono_aot_HelloWorld_init_method
is never generated, looking at the compiler output: https://gist.github.com/ivanpovazan/96542ae24088a4a5e735d414b92e4c9e
there are only jumps to that symbol bl _mono_aot_HelloWorld_init_method
, but it is not generated anywhere.
Signed-off-by: Vlad <[email protected]>
In the current state, the problem with the symbol of the init wrapper persists. There is a mismatch between what is emitted in the non llvm case and what symbol is the init wrapper trying to call. |
Draft Pull Request was automatically closed for 30 days of inactivity. Please let us know if you'd like to reopen it. |
This PR aims to introduce the implementation of method's self initialization for nollvm cases, firstly on Arm64.
This won't be enabled since it's not tested yet.
Addresses #82224.