MonoInst *klass_inst = NULL;
if (context_used) {
- MonoInst *args [2];
+ MonoInst *args [3];
+
+ if(mini_class_has_reference_variant_generic_argument (klass, context_used)) {
+ MonoInst *cache_ins;
+
+ cache_ins = emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_CAST_CACHE);
+
+ /* obj */
+ args [0] = src;
- klass_inst = emit_get_rgctx_klass (cfg, context_used,
- klass, MONO_RGCTX_INFO_KLASS);
+ /* klass - it's the second element of the cache entry*/
+ EMIT_NEW_LOAD_MEMBASE (cfg, args [1], OP_LOAD_MEMBASE, alloc_preg (cfg), cache_ins->dreg, sizeof (gpointer));
+
+ /* cache */
+ args [2] = cache_ins;
+
+ return mono_emit_jit_icall (cfg, mono_object_castclass_with_cache, args);
+ }
+
+ klass_inst = emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_KLASS);
if (is_complex_isinst (klass)) {
/* Complex case, handle by an icall */
MonoInst *klass_inst = NULL;
if (context_used) {
+ MonoInst *args [3];
+
+ if(mini_class_has_reference_variant_generic_argument (klass, context_used)) {
+ MonoInst *cache_ins;
+
+ cache_ins = emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_CAST_CACHE);
+
+ /* obj */
+ args [0] = src;
+
+ /* klass - it's the second element of the cache entry*/
+ EMIT_NEW_LOAD_MEMBASE (cfg, args [1], OP_LOAD_MEMBASE, alloc_preg (cfg), cache_ins->dreg, sizeof (gpointer));
+
+ /* cache */
+ args [2] = cache_ins;
+
+ return mono_emit_jit_icall (cfg, mono_object_isinst_with_cache, args);
+ }
+
klass_inst = emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_KLASS);
if (is_complex_isinst (klass)) {
- MonoInst *args [2];
-
/* Complex case, handle by an icall */
/* obj */
/*FIXME AOT support*/
EMIT_NEW_PCONST (cfg, args [2], mono_domain_alloc0 (cfg->domain, sizeof (gpointer)));
-
ins = mono_emit_jit_icall (cfg, mono_object_castclass_with_cache, args);
*sp ++ = ins;
ip += 5;
#define MONO_RGCTX_SLOT_USED_MARKER ((gpointer)&mono_defaults.object_class->byval_arg)
+/*
+ * Return true if this info type has the notion of identify.
+ *
+ * Some info types expect that each insert results in a new slot been assigned.
+ */
+static int
+other_info_has_identity (int info_type)
+{
+ return info_type != MONO_RGCTX_INFO_CAST_CACHE;
+}
+
/*
* LOCKING: loader lock
*/
case MONO_RGCTX_INFO_KLASS:
case MONO_RGCTX_INFO_VTABLE:
case MONO_RGCTX_INFO_TYPE:
- case MONO_RGCTX_INFO_REFLECTION_TYPE: {
+ case MONO_RGCTX_INFO_REFLECTION_TYPE:
+ case MONO_RGCTX_INFO_CAST_CACHE: {
gpointer result = mono_class_inflate_generic_type_with_mempool (temporary ? NULL : class->image,
data, context, &error);
g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
case MONO_RGCTX_INFO_VTABLE:
case MONO_RGCTX_INFO_TYPE:
case MONO_RGCTX_INFO_REFLECTION_TYPE:
+ case MONO_RGCTX_INFO_CAST_CACHE:
mono_metadata_free_type (info);
break;
default:
mono_raise_exception (mono_class_get_exception_for_failure (class));
return vtable;
}
+ case MONO_RGCTX_INFO_CAST_CACHE: {
+ /*First slot is the cache itself, the second the vtable.*/
+ gpointer **cache_data = mono_domain_alloc0 (domain, sizeof (gpointer) * 2);
+ cache_data [1] = (gpointer)class;
+ return cache_data;
+ }
default:
g_assert_not_reached ();
}
case MONO_RGCTX_INFO_STATIC_DATA:
case MONO_RGCTX_INFO_KLASS:
case MONO_RGCTX_INFO_VTABLE:
+ case MONO_RGCTX_INFO_CAST_CACHE:
temporary = TRUE;
break;
default:
switch (oti->info_type) {
case MONO_RGCTX_INFO_STATIC_DATA:
case MONO_RGCTX_INFO_KLASS:
- case MONO_RGCTX_INFO_VTABLE: {
+ case MONO_RGCTX_INFO_VTABLE:
+ case MONO_RGCTX_INFO_CAST_CACHE: {
MonoClass *arg_class = mono_class_from_mono_type (data);
free_inflated_info (oti->info_type, data);
case MONO_RGCTX_INFO_VTABLE:
case MONO_RGCTX_INFO_TYPE:
case MONO_RGCTX_INFO_REFLECTION_TYPE:
+ case MONO_RGCTX_INFO_CAST_CACHE:
return mono_class_from_mono_type (data1) == mono_class_from_mono_type (data2);
case MONO_RGCTX_INFO_METHOD:
case MONO_RGCTX_INFO_GENERIC_METHOD_CODE:
mono_loader_lock ();
- oti_list = get_other_info_templates (rgctx_template, type_argc);
+ if (other_info_has_identity (info_type)) {
+ oti_list = get_other_info_templates (rgctx_template, type_argc);
- for (oti = oti_list, i = 0; oti; oti = oti->next, ++i) {
- gpointer inflated_data;
+ for (oti = oti_list, i = 0; oti; oti = oti->next, ++i) {
+ gpointer inflated_data;
- if (oti->info_type != info_type || !oti->data)
- continue;
+ if (oti->info_type != info_type || !oti->data)
+ continue;
- inflated_data = inflate_other_info (oti, generic_context, class, TRUE);
+ inflated_data = inflate_other_info (oti, generic_context, class, TRUE);
- if (other_info_equal (data, inflated_data, info_type)) {
+ if (other_info_equal (data, inflated_data, info_type)) {
+ free_inflated_info (info_type, inflated_data);
+ mono_loader_unlock ();
+ return i;
+ }
free_inflated_info (info_type, inflated_data);
- mono_loader_unlock ();
- return i;
}
- free_inflated_info (info_type, inflated_data);
}
/* We haven't found the info */