[runtime] Ensure uniqueness of icall wrappers (#3143)
authorAlexander Kyte <alexmkyte@gmail.com>
Fri, 10 Jun 2016 09:05:51 +0000 (05:05 -0400)
committerZoltan Varga <vargaz@gmail.com>
Fri, 10 Jun 2016 09:05:51 +0000 (05:05 -0400)
commitb1dccbc236c337bb12ec4c7075851b9045c97865
tree78b3b2cfb6ea8e8fd35eee929a85043923b3db81
parentb0fd769485788ceb2958512576c94bb30f661897
[runtime] Ensure uniqueness of icall wrappers (#3143)

The llvmonly backend will use `mono_aot_init_gshared_method_this`
and other initializers to initialize methods. These will transitively call
`mono_icall_get_wrapper_full` when icall wrappers are needed.

The init functions will set the
initialized flag after initialization. They set it in a non-atomic manner. This means that
in a multithreaded environment, it's possible to call the functions
twice.

When `mono_icall_get_wrapper_full` is called without this patch, the
pointers to wrappers it gets from `mono_marshal_get_icall_wrapper`
will not have the same addresses. They will hash to the same value
though.

This will lead to them not being found or inserted by
`find_aot_method_in_amodule`.
The fact that we already have a value with this hash means that
the new wrapper doesn't get inserted. The fact that the pointers differ
mean that we don't say that we've found our desired wrapper.

This leads to an assertion in `mono_icall_get_wrapper_full`
crashing the runtime.

Since we intend to have the semantics of a wrapper for each icall,
this change uses a cache to ensure uniqueness. The observed crashes
do not happen when this change is applied.
mono/metadata/image.c
mono/metadata/marshal.c
mono/metadata/metadata-internals.h