-
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
[mono] Add support for UnmanagedCallersOnlyAttribute #38728
[mono] Add support for UnmanagedCallersOnlyAttribute #38728
Conversation
I couldn't figure out the best area label to add to this PR. If you have write-permissions please help me learn by adding exactly one area label. |
e05143d
to
fe9f96c
Compare
Looks ok. |
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.
LGTM, documenting that this will increase AOT binaries sizes by 1 byte per native-to-managed wrapper AFAICT
1 byte, I think - AOT uses the same value encoding as CIL images - small values (<127) encode to one byte. |
Should pass the positive tests now. Negative tests will still fail. |
I misunderstood the test - it's in fact just crashing. So there's nothing to detect. Mono's behavior of not crashing is ok. |
Some progress on the negative tests. The InvalidProgramException ones should be in good shape. |
The |
…elegate class In that case, create a wrapper based on the signature of the method itself. TODO: - check that the method is static - check that the method does not have any marshal info (currently it's assumed to not be present and ignored)
…thout a delegate class Bump the AOT file format
…llersOnly methods
…wrapper The wrapper might be called from a thread that's not attached to the runtime, and the jump trampoline will look at TLS vars that are not initialized
…agedCallersOnly method
…UnmanagedCallersOnly methods Instead of throwing while JITing (or transforming), throw when the LDFTN is executed.
9317eb0
to
6e85742
Compare
JIT is passing all the tests except |
throw NotSupportedException
Once I see the JIT pass all the tests, I'll bump the test back to Pri1 and then the PR is basically complete. |
From https://helix.dot.net/api/2019-06-17/jobs/51ac422f-058f-4fa3-aa34-f41bb363a4fb/workitems/Interop/console the "runtime (Mono Pri0 Runtime Tests Run OSX x64 release)" JIT job:
As previously mentioned, the interpreter job is failing due to #38897, so this is the best we'll get for now. |
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.
Lots of questions but looks fine to me. Would be really good if Zoltan gets a chance to look at this before it's merged since I'm not terribly confident in my review of the code generation parts. Thanks!
csig = mono_metadata_signature_dup_full (get_method_image (method), sig); | ||
csig->pinvoke = 0; | ||
res = mono_mb_create_and_cache_full (cache, method, mb, csig, | ||
csig->param_count + 16, info, NULL); |
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.
Where is this 16 coming from? It looks like it's used elsewhere, but I'm not familiar enough with this code to understand why.
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 don't know. I'm cargo-culting the other mono_mb_create_and_cache_full
calls in this function.
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.
Ugh, that's what I feared. @vargaz any idea? For my own learning if nothing else :)
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.
No idea, it probably comes from the fact that these are wrappers so the deepest stack will be calling the 'wrapped' method, so param_count + is good for max stack.
src/mono/mono/metadata/marshal.c
Outdated
return NULL; | ||
} | ||
if (!method_signature_is_blittable (invoke_sig)) { | ||
mono_error_set_invalid_program (error, "method %s with UnmanagedCallersOnlyAttribute has non-blittable parameters", mono_method_full_name (method, TRUE)); |
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.
It could also have a non-blittable return type. I'd change this error slightly to reflect that.
src/mono/mono/metadata/marshal.c
Outdated
{ | ||
ERROR_DECL (attr_error); | ||
MonoClass *attr_klass = NULL; | ||
#ifdef ENABLE_NETCORE |
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 guess this accomplishes the same thing, but wouldn't it be clearer to immediately return false on non-netcore?
src/mono/mono/metadata/marshal.c
Outdated
case MONO_TYPE_R8: | ||
case MONO_TYPE_I: | ||
case MONO_TYPE_U: | ||
case MONO_TYPE_CHAR: |
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 char shouldn't be here. Doesn't look like it's supposed to be blittable. (mono_class_setup_mono_type
doesn't set the blittable bit on it)
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.
Ah yeah, good catch. Yes, it's definitely not for the same reason as string—ambiguity over converting to ANSI, UTF-8, or UTF-16.
Co-authored-by: Ryan Lucia <ryan@luciaonline.net>
@@ -3940,10 +3958,54 @@ emit_managed_wrapper_noilgen (MonoMethodBuilder *mb, MonoMethodSignature *invoke | |||
} | |||
#endif | |||
|
|||
static gboolean | |||
type_is_blittable (MonoType *type) |
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.
There is already a class->blittable flag.
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 discussed this, but it's not the same because of byref types.
When we see a method tagged with
UnmanagedCallersOnlyAttribute
in anldtn
instruction, load a pointer to a native-to-managed wrapper instead of a pointer to the managed method.See https://github.com/dotnet/csharplang/blob/master/proposals/functionpointers.md#systemruntimeinteropservicesunmanagedcallersonlyattribute
TODO:
Figure out why the CoreCLR tests are either not running or somehow passing.The tests are in https://github.com/dotnet/runtime/tree/master/src/coreclr/tests/src/Interop/UnmanagedCallersOnly which doesn't seem to be in https://github.com/dotnet/runtime/blob/master/src/coreclr/tests/issues.targets but in that case Mono should be failing a number of the tests in there on CI.It's because we only run P0 tests on CI for Mono. I temporarily set it to P0 for this PR just to watch the tests fail.