* [mono][llvm] Add a fastpath to calling mini_init_method_rgctx ().
* Add arm64 JIT support.
generic_class_init: src1:a len:44 clob:c
gc_safe_point: src1:i len:12 clob:c
+init_mrgctx: src1:a src2:i len:44 clob:c
fill_prof_call_ctx: src1:i len:128
EMIT_NEW_PCONST (cfg, args [1], info);
cfg->init_method_rgctx_ins_arg = args [1];
- cfg->init_method_rgctx_ins = mono_emit_jit_icall (cfg, mini_init_method_rgctx, args);
+ if (COMPILE_LLVM (cfg) || cfg->backend->have_init_mrgctx) {
+ MONO_INST_NEW (cfg, ins, OP_INIT_MRGCTX);
+ ins->sreg1 = args [0]->dreg;
+ ins->sreg2 = args [1]->dreg;
+ MONO_ADD_INS (cfg->cbb, ins);
+ cfg->init_method_rgctx_ins = ins;
+ } else {
+ cfg->init_method_rgctx_ins = mono_emit_jit_icall (cfg, mini_init_method_rgctx, args);
+ }
}
if (cfg->gsharedvt && cfg->method == method) {
mono_arm_patch (jump, code, MONO_R_ARM64_CBZ);
break;
}
+ case OP_INIT_MRGCTX: {
+ int field_offset;
+ guint8 *jump;
+
+ field_offset = MONO_STRUCT_OFFSET (MonoMethodRuntimeGenericContext, entries);
+
+ /* Load mrgxtx->entries */
+ arm_ldrx (code, ARMREG_IP0, sreg1, field_offset);
+ jump = code;
+ arm_cbnzx (code, ARMREG_IP0, 0);
+
+ /* Slowpath */
+ g_assert (sreg1 == ARMREG_R0);
+ if (sreg2 != ARMREG_R1)
+ arm_movx (code, ARMREG_R1, sreg2);
+ code = emit_call (cfg, code, MONO_PATCH_INFO_JIT_ICALL_ID,
+ GUINT_TO_POINTER (MONO_JIT_ICALL_mini_init_method_rgctx));
+
+ mono_arm_patch (jump, code, MONO_R_ARM64_CBZ);
+ break;
+ }
case OP_CHECK_THIS:
arm_ldrb (code, ARMREG_LR, sreg1, 0);
#define MONO_ARCH_HAVE_DECOMPOSE_LONG_OPTS 1
#define MONO_ARCH_FLOAT32_SUPPORTED 1
#define MONO_ARCH_HAVE_INTERP_PINVOKE_TRAMP 1
+#define MONO_ARCH_HAVE_INIT_MRGCTX 1
#define MONO_ARCH_LLVM_TARGET_LAYOUT "e-i64:64-i128:128-n32:64-S128"
#ifdef TARGET_OSX
#define MONO_ARCH_FORCE_FLOAT32 1
break;
}
+ case OP_INIT_MRGCTX: {
+ LLVMValueRef val, cmp, callee;
+ LLVMBasicBlockRef poll_bb, cont_bb;
+ LLVMValueRef args [2];
+ static LLVMTypeRef icall_sig;
+
+ g_assert (cfg->compile_aot);
+
+ /*
+ * if (!((MonoMethodRuntimeGenericContext)->lhs)->entries)
+ * mini_init_method_rgctx (lhs, rhs);
+ */
+
+ LLVMValueRef offset = const_int32 (MONO_STRUCT_OFFSET (MonoMethodRuntimeGenericContext, entries));
+ LLVMValueRef ptr = LLVMBuildAdd (builder, convert (ctx, lhs, IntPtrType ()), convert (ctx, offset, IntPtrType ()), "");
+
+ val = emit_load (builder, IntPtrType (), convert (ctx, ptr, pointer_type (IntPtrType ())), "", TRUE);
+ cmp = LLVMBuildICmp (builder, LLVMIntEQ, val, LLVMConstNull (LLVMTypeOf (val)), "");
+ poll_bb = gen_bb (ctx, "POLL_BB");
+ cont_bb = gen_bb (ctx, "CONT_BB");
+
+ args [0] = cmp;
+ args [1] = LLVMConstInt (LLVMInt1Type (), 0, FALSE);
+ cmp = call_intrins (ctx, INTRINS_EXPECT_I1, args, "");
+
+ mono_llvm_build_weighted_branch (builder, cmp, poll_bb, cont_bb, 1, 1000);
+
+ ctx->builder = builder = create_builder (ctx);
+ LLVMPositionBuilderAtEnd (builder, poll_bb);
+
+ if (!icall_sig)
+ icall_sig = LLVMFunctionType2 (LLVMVoidType (), IntPtrType (), IntPtrType (), FALSE);
+
+ args [0] = convert (ctx, lhs, IntPtrType ());
+ args [1] = convert (ctx, rhs, IntPtrType ());
+
+ callee = get_callee (ctx, icall_sig, MONO_PATCH_INFO_JIT_ICALL_ID, GUINT_TO_POINTER (MONO_JIT_ICALL_mini_init_method_rgctx));
+ LLVMBuildCall2 (builder, icall_sig, callee, args, 2, "");
+ LLVMBuildBr (builder, cont_bb);
+
+ ctx->builder = builder = create_builder (ctx);
+ LLVMPositionBuilderAtEnd (builder, cont_bb);
+ ctx->bblocks [bb->block_num].end_bblock = cont_bb;
+ break;
+ }
+
/*
* Overflow opcodes.
*/
*/
MINI_OP(OP_GENERIC_CLASS_INIT, "generic_class_init", NONE, IREG, NONE)
+/*
+ * Call mini_init_method_rgctx () if needed.
+ * sreg1 is a MonoMethodRuntimeGenericContext.
+ * sreg2 is a MonoGSharedMethodInfo.
+ */
+MINI_OP(OP_INIT_MRGCTX, "init_mrgctx", NONE, IREG, IREG)
+
/* Arch specific opcodes */
#if defined(TARGET_X86) || defined(TARGET_AMD64)
MINI_OP(OP_X86_TEST_NULL, "x86_test_null", NONE, IREG, NONE)
#ifdef MONO_ARCH_FORCE_FLOAT32
backend->force_float32 = 1;
#endif
+#ifdef MONO_ARCH_HAVE_INIT_MRGCTX
+ backend->have_init_mrgctx = 1;
+#endif
}
static gboolean
gboolean have_op_tailcall_membase : 1;
gboolean have_op_tailcall_reg : 1;
gboolean have_volatile_non_param_register : 1;
+ guint have_init_mrgctx : 1;
guint gshared_supported : 1;
guint ilp32 : 1;
guint need_got_var : 1;