c.throw_catch_t ();
return 0;
}
+
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ public static bool is_ref_or_contains_refs<T> () {
+ return RuntimeHelpers.IsReferenceOrContainsReferences<T> ();
+ }
+
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ public static bool is_ref_or_contains_refs_gen_ref<T> () {
+ return RuntimeHelpers.IsReferenceOrContainsReferences<GenStruct<T>> ();
+ }
+
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ public static bool is_ref_or_contains_refs_gen_noref<T> () {
+ return RuntimeHelpers.IsReferenceOrContainsReferences<NoRefGenStruct<T>> ();
+ }
+
+ struct GenStruct<T> {
+ T t;
+ }
+
+ struct NoRefGenStruct<T> {
+ }
+
+ struct RefStruct {
+ string s;
+ }
+
+ struct NestedRefStruct {
+ RefStruct r;
+ }
+
+ struct NoRefStruct {
+ int i;
+ }
+
+ public static int test_0_isreference_intrins () {
+ if (RuntimeHelpers.IsReferenceOrContainsReferences<int> ())
+ return 1;
+ if (!RuntimeHelpers.IsReferenceOrContainsReferences<string> ())
+ return 2;
+ if (!RuntimeHelpers.IsReferenceOrContainsReferences<RefStruct> ())
+ return 3;
+ if (!RuntimeHelpers.IsReferenceOrContainsReferences<NestedRefStruct> ())
+ return 4;
+ if (RuntimeHelpers.IsReferenceOrContainsReferences<NoRefStruct> ())
+ return 5;
+ // Generic code
+ if (is_ref_or_contains_refs<int> ())
+ return 6;
+ // Shared code
+ if (!is_ref_or_contains_refs<string> ())
+ return 7;
+ // Complex type from shared code
+ if (!is_ref_or_contains_refs_gen_ref<string> ())
+ return 8;
+ if (is_ref_or_contains_refs_gen_ref<int> ())
+ return 9;
+ if (is_ref_or_contains_refs_gen_noref<string> ())
+ return 10;
+
+ return 0;
+ }
}
#if !__MOBILE__
mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
{
MonoInst *ins = NULL;
-
- MonoClass *runtime_helpers_class = mono_class_get_runtime_helpers_class ();
+ MonoClass *runtime_helpers_class = mono_class_get_runtime_helpers_class ();
if (cmethod->klass == mono_defaults.string_class) {
if (strcmp (cmethod->name, "get_Chars") == 0 && fsig->param_count + fsig->hasthis == 2) {
} else if (cmethod->klass == runtime_helpers_class) {
if (strcmp (cmethod->name, "get_OffsetToStringData") == 0 && fsig->param_count == 0) {
EMIT_NEW_ICONST (cfg, ins, MONO_STRUCT_OFFSET (MonoString, chars));
+ return ins;
+ } else if (strcmp (cmethod->name, "IsReferenceOrContainsReferences") == 0 && fsig->param_count == 0) {
+ MonoGenericContext *ctx = mono_method_get_context (cmethod);
+ g_assert (ctx);
+ g_assert (ctx->method_inst);
+ g_assert (ctx->method_inst->type_argc == 1);
+ MonoType *t = mini_get_underlying_type (ctx->method_inst->type_argv [0]);
+ MonoClass *klass = mono_class_from_mono_type (t);
+
+ ins = NULL;
+
+ mono_class_init (klass);
+ if (MONO_TYPE_IS_REFERENCE (t))
+ EMIT_NEW_ICONST (cfg, ins, 1);
+ else if (MONO_TYPE_IS_PRIMITIVE (t))
+ EMIT_NEW_ICONST (cfg, ins, 0);
+ else if (cfg->gshared && (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) && !mini_type_var_is_vt (t))
+ EMIT_NEW_ICONST (cfg, ins, 1);
+ else if (!cfg->gshared || !mini_class_check_context_used (cfg, klass))
+ EMIT_NEW_ICONST (cfg, ins, klass->has_references ? 1 : 0);
+ else {
+ g_assert (cfg->gshared);
+
+ int context_used = mini_class_check_context_used (cfg, klass);
+
+ /* This returns 1 or 2 */
+ MonoInst *info = mini_emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_CLASS_IS_REF_OR_CONTAINS_REFS);
+ int dreg = alloc_ireg (cfg);
+ EMIT_NEW_BIALU_IMM (cfg, ins, OP_ISUB_IMM, dreg, info->dreg, 1);
+ }
+
return ins;
} else
return NULL;
case MONO_RGCTX_INFO_ARRAY_ELEMENT_SIZE:
case MONO_RGCTX_INFO_VALUE_SIZE:
case MONO_RGCTX_INFO_CLASS_BOX_TYPE:
+ case MONO_RGCTX_INFO_CLASS_IS_REF_OR_CONTAINS_REFS:
case MONO_RGCTX_INFO_MEMCPY:
case MONO_RGCTX_INFO_BZERO:
case MONO_RGCTX_INFO_LOCAL_OFFSET:
return GUINT_TO_POINTER (MONO_GSHAREDVT_BOX_TYPE_NULLABLE);
else
return GUINT_TO_POINTER (MONO_GSHAREDVT_BOX_TYPE_VTYPE);
+ case MONO_RGCTX_INFO_CLASS_IS_REF_OR_CONTAINS_REFS:
+ mono_class_init (klass);
+ /* Can't return 0 */
+ if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg) || klass->has_references)
+ return GUINT_TO_POINTER (2);
+ else
+ return GUINT_TO_POINTER (1);
case MONO_RGCTX_INFO_MEMCPY:
case MONO_RGCTX_INFO_BZERO: {
static MonoMethod *memcpy_method [17];
case MONO_RGCTX_INFO_ARRAY_ELEMENT_SIZE:
case MONO_RGCTX_INFO_VALUE_SIZE:
case MONO_RGCTX_INFO_CLASS_BOX_TYPE:
+ case MONO_RGCTX_INFO_CLASS_IS_REF_OR_CONTAINS_REFS:
case MONO_RGCTX_INFO_MEMCPY:
case MONO_RGCTX_INFO_BZERO:
case MONO_RGCTX_INFO_NULLABLE_CLASS_BOX:
case MONO_RGCTX_INFO_ARRAY_ELEMENT_SIZE: return "ARRAY_ELEMENT_SIZE";
case MONO_RGCTX_INFO_VALUE_SIZE: return "VALUE_SIZE";
case MONO_RGCTX_INFO_CLASS_BOX_TYPE: return "CLASS_BOX_TYPE";
+ case MONO_RGCTX_INFO_CLASS_IS_REF_OR_CONTAINS_REFS: return "CLASS_IS_REF_OR_CONTAINS_REFS";
case MONO_RGCTX_INFO_FIELD_OFFSET: return "FIELD_OFFSET";
case MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE: return "METHOD_GSHAREDVT_OUT_TRAMPOLINE";
case MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE_VIRT: return "METHOD_GSHAREDVT_OUT_TRAMPOLINE_VIRT";
case MONO_RGCTX_INFO_ARRAY_ELEMENT_SIZE:
case MONO_RGCTX_INFO_VALUE_SIZE:
case MONO_RGCTX_INFO_CLASS_BOX_TYPE:
+ case MONO_RGCTX_INFO_CLASS_IS_REF_OR_CONTAINS_REFS:
case MONO_RGCTX_INFO_MEMCPY:
case MONO_RGCTX_INFO_BZERO:
case MONO_RGCTX_INFO_NULLABLE_CLASS_BOX:
case MONO_RGCTX_INFO_ARRAY_ELEMENT_SIZE:
case MONO_RGCTX_INFO_VALUE_SIZE:
case MONO_RGCTX_INFO_CLASS_BOX_TYPE:
+ case MONO_RGCTX_INFO_CLASS_IS_REF_OR_CONTAINS_REFS:
case MONO_RGCTX_INFO_MEMCPY:
case MONO_RGCTX_INFO_BZERO:
case MONO_RGCTX_INFO_NULLABLE_CLASS_BOX:
* which implements the method.
*/
MONO_RGCTX_INFO_VIRT_METHOD_BOX_TYPE,
+ /* Resolve to 2 (TRUE) or 1 (FALSE) */
+ MONO_RGCTX_INFO_CLASS_IS_REF_OR_CONTAINS_REFS
} MonoRgctxInfoType;
typedef struct _MonoRuntimeGenericContextInfoTemplate {