case MONO_PATCH_INFO_AOT_MODULE:
break;
case MONO_PATCH_INFO_SIGNATURE:
+ case MONO_PATCH_INFO_GSHAREDVT_IN_WRAPPER:
encode_signature (acfg, (MonoMethodSignature*)patch_info->data.target, p, &p);
break;
case MONO_PATCH_INFO_TLS_OFFSET:
static const char *preinited_jit_icalls[] = {
"mono_aot_init_llvm_method",
"mono_aot_init_gshared_method_this",
- "mono_aot_init_gshared_method_rgctx",
+ "mono_aot_init_gshared_method_mrgctx",
+ "mono_aot_init_gshared_method_vtable",
"mono_llvm_throw_corlib_exception",
"mono_init_vtable_slot",
"mono_helper_ldstr_mscorlib"
case MONO_PATCH_INFO_MSCORLIB_GOT_ADDR:
break;
case MONO_PATCH_INFO_SIGNATURE:
+ case MONO_PATCH_INFO_GSHAREDVT_IN_WRAPPER:
ji->data.target = decode_signature (aot_module, p, &p);
break;
case MONO_PATCH_INFO_TLS_OFFSET:
}
void
-mono_aot_init_gshared_method_rgctx (gpointer aot_module, guint32 method_index, MonoMethodRuntimeGenericContext *rgctx)
+mono_aot_init_gshared_method_mrgctx (gpointer aot_module, guint32 method_index, MonoMethodRuntimeGenericContext *rgctx)
{
MonoAotModule *amodule = (MonoAotModule *)aot_module;
gboolean res;
g_assert (res);
}
+void
+mono_aot_init_gshared_method_vtable (gpointer aot_module, guint32 method_index, MonoVTable *vtable)
+{
+ MonoAotModule *amodule = (MonoAotModule *)aot_module;
+ gboolean res;
+ MonoClass *klass;
+ MonoGenericContext *context;
+ MonoMethod *method;
+
+ klass = vtable->klass;
+
+ amodule_lock (amodule);
+ method = (MonoMethod *)g_hash_table_lookup (amodule->extra_methods, GUINT_TO_POINTER (method_index));
+ amodule_unlock (amodule);
+
+ g_assert (method);
+ context = mono_method_get_context (method);
+ g_assert (context);
+
+ res = init_llvm_method (amodule, method_index, NULL, klass, context);
+ g_assert (res);
+}
+
/*
* mono_aot_get_method:
*
}
void
-mono_aot_init_gshared_method_rgctx (gpointer aot_module, guint32 method_index, MonoMethodRuntimeGenericContext *rgctx)
+mono_aot_init_gshared_method_mrgctx (gpointer aot_module, guint32 method_index, MonoMethodRuntimeGenericContext *rgctx)
+{
+}
+
+void
+mono_aot_init_gshared_method_vtable (gpointer aot_module, guint32 method_index, MonoVTable *vtable)
{
}
MONO_START_BB (cfg, end_bb);
} else {
- ins = emit_extra_arg_calli (cfg, fsig, sp, arg->dreg, addr);
+ /* Caller uses a normal calling conv */
+
+ MonoInst *callee = addr;
+ MonoInst *call, *localloc_ins;
+ MonoBasicBlock *is_gsharedvt_bb, *end_bb;
+ int low_bit_reg = alloc_preg (cfg);
+
+ NEW_BBLOCK (cfg, is_gsharedvt_bb);
+ NEW_BBLOCK (cfg, end_bb);
+
+ MONO_EMIT_NEW_BIALU_IMM (cfg, OP_PAND_IMM, low_bit_reg, arg->dreg, 1);
+ MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, low_bit_reg, 0);
+ MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBNE_UN, is_gsharedvt_bb);
+
+ /* Normal case: callee uses a normal cconv, no conversion is needed */
+ call = emit_extra_arg_calli (cfg, fsig, sp, arg->dreg, callee);
+ MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
+ /* Gsharedvt case: callee uses a gsharedvt cconv, have to add an in wrapper */
+ MONO_START_BB (cfg, is_gsharedvt_bb);
+ MONO_EMIT_NEW_BIALU_IMM (cfg, OP_PXOR_IMM, arg->dreg, arg->dreg, 1);
+ NEW_AOTCONST (cfg, addr, MONO_PATCH_INFO_GSHAREDVT_IN_WRAPPER, fsig);
+ MONO_ADD_INS (cfg->cbb, addr);
+ /*
+ * ADDR points to a gsharedvt-in wrapper, have to pass <callee, arg> as an extra arg.
+ */
+ MONO_INST_NEW (cfg, ins, OP_LOCALLOC_IMM);
+ ins->dreg = alloc_preg (cfg);
+ ins->inst_imm = 2 * SIZEOF_VOID_P;
+ MONO_ADD_INS (cfg->cbb, ins);
+ localloc_ins = ins;
+ cfg->flags |= MONO_CFG_HAS_ALLOCA;
+ MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, localloc_ins->dreg, 0, callee->dreg);
+ MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, localloc_ins->dreg, SIZEOF_VOID_P, arg->dreg);
+
+ ins = emit_extra_arg_calli (cfg, fsig, sp, localloc_ins->dreg, addr);
+ ins->dreg = call->dreg;
+ MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
+
+ MONO_START_BB (cfg, end_bb);
}
} else {
/* Same as CEE_CALLI */
return &inflated_class->fields [i];
}
+ case MONO_RGCTX_INFO_SIG_GSHAREDVT_IN_TRAMPOLINE_CALLI:
case MONO_RGCTX_INFO_SIG_GSHAREDVT_OUT_TRAMPOLINE_CALLI: {
MonoMethodSignature *sig = (MonoMethodSignature *)data;
MonoMethodSignature *isig;
return method->context.method_inst;
}
+ case MONO_RGCTX_INFO_SIG_GSHAREDVT_IN_TRAMPOLINE_CALLI: {
+ MonoMethodSignature *gsig = (MonoMethodSignature *)oti->data;
+ MonoMethodSignature *sig = (MonoMethodSignature *)data;
+ gpointer addr;
+
+ /*
+ * This is an indirect call to the address passed by the caller in the rgctx reg.
+ */
+ addr = mini_get_gsharedvt_wrapper (TRUE, NULL, sig, gsig, -1, TRUE);
+ return addr;
+ }
case MONO_RGCTX_INFO_SIG_GSHAREDVT_OUT_TRAMPOLINE_CALLI: {
MonoMethodSignature *gsig = (MonoMethodSignature *)oti->data;
MonoMethodSignature *sig = (MonoMethodSignature *)data;
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_SIG_GSHAREDVT_IN_TRAMPOLINE_CALLI: return "SIG_GSHAREDVT_IN_TRAMPOLINE_CALLI";
case MONO_RGCTX_INFO_SIG_GSHAREDVT_OUT_TRAMPOLINE_CALLI: return "SIG_GSHAREDVT_OUT_TRAMPOLINE_CALLI";
case MONO_RGCTX_INFO_MEMCPY: return "MEMCPY";
case MONO_RGCTX_INFO_BZERO: return "BZERO";
case MONO_RGCTX_INFO_METHOD_DELEGATE_CODE:
case MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE:
case MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE_VIRT:
+ case MONO_RGCTX_INFO_SIG_GSHAREDVT_IN_TRAMPOLINE_CALLI:
case MONO_RGCTX_INFO_SIG_GSHAREDVT_OUT_TRAMPOLINE_CALLI:
return data1 == data2;
case MONO_RGCTX_INFO_VIRT_METHOD_CODE:
const char *jit_got_symbol;
const char *eh_frame_symbol;
LLVMValueRef get_method, get_unbox_tramp;
- LLVMValueRef init_method, init_method_gshared_rgctx, init_method_gshared_this;
+ LLVMValueRef init_method, init_method_gshared_mrgctx, init_method_gshared_this, init_method_gshared_vtable;
LLVMValueRef code_start, code_end;
LLVMValueRef inited_var;
int max_inited_idx, max_method_idx;
func = LLVMAddFunction (lmodule, module->get_unbox_tramp_symbol, LLVMFunctionType1 (rtype, LLVMInt32Type (), FALSE));
LLVMSetLinkage (func, LLVMExternalLinkage);
LLVMSetVisibility (func, LLVMHiddenVisibility);
- LLVMAddFunctionAttr (func, LLVMNoUnwindAttribute);
module->get_unbox_tramp = func;
entry_bb = LLVMAppendBasicBlock (func, "ENTRY");
sig = LLVMFunctionType2 (LLVMVoidType (), IntPtrType (), LLVMInt32Type (), FALSE);
break;
case 1:
+ case 3:
+ /* mrgctx/vtable */
func = LLVMAddFunction (lmodule, name, LLVMFunctionType2 (LLVMVoidType (), LLVMInt32Type (), IntPtrType (), FALSE));
sig = LLVMFunctionType3 (LLVMVoidType (), IntPtrType (), LLVMInt32Type (), IntPtrType (), FALSE);
break;
emit_init_icall_wrappers (MonoLLVMModule *module)
{
module->init_method = emit_init_icall_wrapper (module, "init_method", "mono_aot_init_llvm_method", 0);
- module->init_method_gshared_rgctx = emit_init_icall_wrapper (module, "init_method_gshared_rgctx", "mono_aot_init_gshared_method_rgctx", 1);
+ module->init_method_gshared_mrgctx = emit_init_icall_wrapper (module, "init_method_gshared_mrgctx", "mono_aot_init_gshared_method_mrgctx", 1);
module->init_method_gshared_this = emit_init_icall_wrapper (module, "init_method_gshared_this", "mono_aot_init_gshared_method_this", 2);
+ module->init_method_gshared_vtable = emit_init_icall_wrapper (module, "init_method_gshared_vtable", "mono_aot_init_gshared_method_vtable", 3);
}
static void
LLVMPositionBuilderAtEnd (ctx->builder, notinited_bb);
// FIXME: Cache
- if (ctx->rgctx_arg) {
+ if (ctx->rgctx_arg && cfg->method->is_inflated && mono_method_get_context (cfg->method)->method_inst) {
+ args [0] = LLVMConstInt (LLVMInt32Type (), cfg->method_index, 0);
+ args [1] = convert (ctx, ctx->rgctx_arg, IntPtrType ());
+ callee = ctx->module->init_method_gshared_mrgctx;
+ call = LLVMBuildCall (builder, callee, args, 2, "");
+ } else if (ctx->rgctx_arg) {
+ /* A vtable is passed as the rgctx argument */
args [0] = LLVMConstInt (LLVMInt32Type (), cfg->method_index, 0);
args [1] = convert (ctx, ctx->rgctx_arg, IntPtrType ());
- callee = ctx->module->init_method_gshared_rgctx;
+ callee = ctx->module->init_method_gshared_vtable;
call = LLVMBuildCall (builder, callee, args, 2, "");
} else if (cfg->gshared) {
args [0] = LLVMConstInt (LLVMInt32Type (), cfg->method_index, 0);
}
case MONO_PATCH_INFO_JIT_ICALL_ADDR:
return (ji->type << 8) | g_str_hash (ji->data.target);
+ case MONO_PATCH_INFO_GSHAREDVT_IN_WRAPPER:
+ return (ji->type << 8) | mono_signature_hash (ji->data.sig);
default:
printf ("info type: %d\n", ji->type);
mono_print_ji (ji); printf ("\n");
if (ji1->data.target == ji2->data.target)
return 1;
return strcmp (ji1->data.target, ji2->data.target) == 0 ? 1 : 0;
+ case MONO_PATCH_INFO_GSHAREDVT_IN_WRAPPER:
+ return mono_metadata_signature_equal (ji1->data.sig, ji2->data.sig) ? 0 : 1;
default:
if (ji1->data.target != ji2->data.target)
return 0;
break;
}
+ case MONO_PATCH_INFO_GSHAREDVT_IN_WRAPPER:
+ target = mini_get_gsharedvt_wrapper (TRUE, NULL, patch_info->data.sig, NULL, -1, FALSE);
+ break;
default:
g_assert_not_reached ();
}
register_icall (mono_aot_init_llvm_method, "mono_aot_init_llvm_method", "void ptr int", TRUE);
register_icall (mono_aot_init_gshared_method_this, "mono_aot_init_gshared_method_this", "void ptr int object", TRUE);
- register_icall (mono_aot_init_gshared_method_rgctx, "mono_aot_init_gshared_method_rgctx", "void ptr int ptr", TRUE);
+ register_icall (mono_aot_init_gshared_method_mrgctx, "mono_aot_init_gshared_method_mrgctx", "void ptr int ptr", TRUE);
+ register_icall (mono_aot_init_gshared_method_vtable, "mono_aot_init_gshared_method_vtable", "void ptr int ptr", TRUE);
register_icall_no_wrapper (mono_resolve_iface_call_gsharedvt, "mono_resolve_iface_call_gsharedvt", "ptr object int ptr ptr");
register_icall_no_wrapper (mono_resolve_vcall_gsharedvt, "mono_resolve_vcall_gsharedvt", "ptr object int ptr ptr");
#endif
/* Version number of the AOT file format */
-#define MONO_AOT_FILE_VERSION 130
+#define MONO_AOT_FILE_VERSION 131
//TODO: This is x86/amd64 specific.
#define mono_simd_shuffle_mask(a,b,c,d) ((a) | ((b) << 2) | ((c) << 4) | ((d) << 6))
MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE_VIRT,
/* Same for calli, associated with a signature */
MONO_RGCTX_INFO_SIG_GSHAREDVT_OUT_TRAMPOLINE_CALLI,
+ MONO_RGCTX_INFO_SIG_GSHAREDVT_IN_TRAMPOLINE_CALLI,
/* One of MONO_GSHAREDVT_BOX_TYPE */
MONO_RGCTX_INFO_CLASS_BOX_TYPE,
/* Resolves to a MonoGSharedVtMethodRuntimeInfo */
guint32 mono_aot_find_method_index (MonoMethod *method);
void mono_aot_init_llvm_method (gpointer aot_module, guint32 method_index);
void mono_aot_init_gshared_method_this (gpointer aot_module, guint32 method_index, MonoObject *this_ins);
-void mono_aot_init_gshared_method_rgctx (gpointer aot_module, guint32 method_index, MonoMethodRuntimeGenericContext *rgctx);
+void mono_aot_init_gshared_method_mrgctx (gpointer aot_module, guint32 method_index, MonoMethodRuntimeGenericContext *rgctx);
+void mono_aot_init_gshared_method_vtable (gpointer aot_module, guint32 method_index, MonoVTable *vtable);
/* This is an exported function */
MONO_API void mono_aot_register_module (gpointer *aot_info);
PATCH_INFO(AOT_MODULE, "aot_module")
PATCH_INFO(AOT_JIT_INFO, "aot_jit_info")
PATCH_INFO(GC_NURSERY_BITS, "gc_nursery_bits")
+PATCH_INFO(GSHAREDVT_IN_WRAPPER, "gsharedvt_in_wrapper")