return m;
}
-MonoObject*
-mono_object_tostring_gsharedvt (gpointer mp, MonoMethod *cmethod, MonoClass *klass)
-{
- MonoMethod *m;
- gpointer this_arg;
-
- m = constrained_gsharedvt_call_setup (mp, cmethod, klass, &this_arg);
- return mono_runtime_invoke (m, this_arg, NULL, NULL);
-}
-
-int
-mono_object_gethashcode_gsharedvt (gpointer mp, MonoMethod *cmethod, MonoClass *klass)
-{
- MonoMethod *m;
- gpointer this_arg;
- MonoObject *res;
- gpointer p;
-
- m = constrained_gsharedvt_call_setup (mp, cmethod, klass, &this_arg);
- // FIXME: This boxes the result
- res = mono_runtime_invoke (m, this_arg, NULL, NULL);
- p = mono_object_unbox (res);
- return *(int*)p;
-}
-
-MonoBoolean
-mono_object_equals_gsharedvt (gpointer mp, MonoMethod *cmethod, MonoClass *klass, MonoObject *arg)
-{
- MonoMethod *m;
- gpointer this_arg;
- MonoObject *res;
- gpointer p;
- void **args;
-
- m = constrained_gsharedvt_call_setup (mp, cmethod, klass, &this_arg);
- // FIXME: This boxes the result
- args = (void**)&arg;
- res = mono_runtime_invoke (m, this_arg, args, NULL);
- p = mono_object_unbox (res);
- return *(MonoBoolean*)p;
-}
-
/*
* mono_gsharedvt_constrained_call:
*
* Make a call to CMETHOD using the receiver MP, which is assumed to be of type KLASS. ARGS contains
* the arguments to the method in the format used by mono_runtime_invoke ().
*/
-void
+MonoObject*
mono_gsharedvt_constrained_call (gpointer mp, MonoMethod *cmethod, MonoClass *klass, gpointer *args)
{
MonoMethod *m;
gpointer this_arg;
m = constrained_gsharedvt_call_setup (mp, cmethod, klass, &this_arg);
- mono_runtime_invoke (m, this_arg, args, NULL);
+ return mono_runtime_invoke (m, this_arg, args, NULL);
}
void
MonoObject*
mono_object_castclass_with_cache (MonoObject *obj, MonoClass *klass, gpointer *cache);
-MonoObject* mono_object_tostring_gsharedvt (gpointer mp, MonoMethod *cmethod, MonoClass *klass) MONO_INTERNAL;
-
-int mono_object_gethashcode_gsharedvt (gpointer mp, MonoMethod *cmethod, MonoClass *klass) MONO_INTERNAL;
-
-MonoBoolean mono_object_equals_gsharedvt (gpointer mp, MonoMethod *cmethod, MonoClass *klass, MonoObject *arg) MONO_INTERNAL;
-
-void mono_gsharedvt_constrained_call (gpointer mp, MonoMethod *cmethod, MonoClass *klass, gpointer *args) MONO_INTERNAL;
+MonoObject*
+mono_gsharedvt_constrained_call (gpointer mp, MonoMethod *cmethod, MonoClass *klass, gpointer *args) MONO_INTERNAL;
void mono_gsharedvt_value_copy (gpointer dest, gpointer src, MonoClass *klass) MONO_INTERNAL;
/*
* Constrained calls need to behave differently at runtime dependending on whenever the receiver is instantiated as ref type or as a vtype.
*/
- /* Special case Object methods as they are easy to implement */
- if (cmethod->klass == mono_defaults.object_class) {
- MonoInst *args [16];
-
- args [0] = sp [0];
- EMIT_NEW_METHODCONST (cfg, args [1], cmethod);
- args [2] = emit_get_rgctx_klass (cfg, mono_class_check_context_used (constrained_call), constrained_call, MONO_RGCTX_INFO_KLASS);
-
- if (!strcmp (cmethod->name, "ToString")) {
- ins = mono_emit_jit_icall (cfg, mono_object_tostring_gsharedvt, args);
- } else if (!strcmp (cmethod->name, "Equals")) {
- args [3] = sp [1];
- ins = mono_emit_jit_icall (cfg, mono_object_equals_gsharedvt, args);
- } else if (!strcmp (cmethod->name, "GetHashCode")) {
- ins = mono_emit_jit_icall (cfg, mono_object_gethashcode_gsharedvt, args);
- } else {
- GSHAREDVT_FAILURE (*ip);
- }
- goto call_end;
- } else if (constrained_call->valuetype && cmethod->klass->valuetype) {
+ if ((cmethod->klass != mono_defaults.object_class) && constrained_call->valuetype && cmethod->klass->valuetype) {
/* The 'Own method' case below */
- } else if ((cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE) && MONO_TYPE_IS_VOID (fsig->ret) && (fsig->param_count == 0 || (fsig->param_count == 1 && MONO_TYPE_IS_REFERENCE (fsig->params [0])))) {
+ } else if (((cmethod->klass == mono_defaults.object_class) || (cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE)) &&
+ (MONO_TYPE_IS_VOID (fsig->ret) || fsig->ret->type == MONO_TYPE_I4 || fsig->ret->type == MONO_TYPE_BOOLEAN || fsig->ret->type == MONO_TYPE_STRING) &&
+ (fsig->param_count == 0 || (fsig->param_count == 1 && MONO_TYPE_IS_REFERENCE (fsig->params [0])))) {
MonoInst *args [16];
+ /*
+ * This case handles calls to object:ToString()/Equals()/GetHashCode(), plus some simple interface calls enough to support
+ * AsyncTaskMethodBuilder.
+ */
+
args [0] = sp [0];
EMIT_NEW_METHODCONST (cfg, args [1], cmethod);
args [2] = emit_get_rgctx_klass (cfg, mono_class_check_context_used (constrained_call), constrained_call, MONO_RGCTX_INFO_KLASS);
} else {
EMIT_NEW_ICONST (cfg, args [3], 0);
}
-
ins = mono_emit_jit_icall (cfg, mono_gsharedvt_constrained_call, args);
+ emit_widen = FALSE;
+
+ if (fsig->ret->type == MONO_TYPE_I4 || fsig->ret->type == MONO_TYPE_BOOLEAN) {
+ MonoInst *add;
+ int dreg;
+
+ /* Unbox */
+ NEW_BIALU_IMM (cfg, add, OP_ADD_IMM, alloc_dreg (cfg, STACK_MP), ins->dreg, sizeof (MonoObject));
+ MONO_ADD_INS (cfg->cbb, add);
+ dreg = alloc_ireg (cfg);
+ /* Load value */
+ if (fsig->ret->type == MONO_TYPE_BOOLEAN)
+ NEW_LOAD_MEMBASE (cfg, ins, OP_LOADU1_MEMBASE, dreg, add->dreg, 0);
+ else
+ NEW_LOAD_MEMBASE (cfg, ins, OP_LOADI4_MEMBASE, dreg, add->dreg, 0);
+ MONO_ADD_INS (cfg->cbb, ins);
+ /* ins represents the call result */
+ }
+
goto call_end;
} else {
GSHAREDVT_FAILURE (*ip);
register_icall (mono_array_new_4, "mono_array_new_4", "object ptr int int int int", FALSE);
register_icall (mono_get_native_calli_wrapper, "mono_get_native_calli_wrapper", "ptr ptr ptr ptr", FALSE);
register_icall (mono_resume_unwind, "mono_resume_unwind", "void", TRUE);
- register_icall (mono_object_tostring_gsharedvt, "mono_object_tostring_gsharedvt", "object ptr ptr ptr", TRUE);
- register_icall (mono_object_gethashcode_gsharedvt, "mono_object_gethashcode_gsharedvt", "int ptr ptr ptr", TRUE);
- register_icall (mono_object_equals_gsharedvt, "mono_object_equals_gsharedvt", "int ptr ptr ptr object", TRUE);
- register_icall (mono_gsharedvt_constrained_call, "mono_gsharedvt_constrained_call", "void ptr ptr ptr ptr", TRUE);
+ register_icall (mono_gsharedvt_constrained_call, "mono_gsharedvt_constrained_call", "object ptr ptr ptr ptr", TRUE);
register_icall (mono_gsharedvt_value_copy, "mono_gsharedvt_value_copy", "void ptr ptr ptr", TRUE);
register_icall (mono_gc_wbarrier_value_copy_bitmap, "mono_gc_wbarrier_value_copy_bitmap", "void ptr ptr int int", FALSE);