+ /* Inline version, not currently used */
+ // FIXME: This can be called from mono_decompose_vtype_opts (), which can't create new bblocks
+#if 0
+ int i, slot, depth, index, rgctx_reg, val_reg, res_reg;
+ gboolean mrgctx;
+ MonoBasicBlock *is_null_bb, *end_bb;
+ MonoInst *res, *ins, *call;
+ MonoInst *args[16];
+
+ slot = mini_get_rgctx_entry_slot (entry);
+
+ mrgctx = MONO_RGCTX_SLOT_IS_MRGCTX (slot);
+ index = MONO_RGCTX_SLOT_INDEX (slot);
+ if (mrgctx)
+ index += MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT / sizeof (gpointer);
+ for (depth = 0; ; ++depth) {
+ int size = mono_class_rgctx_get_array_size (depth, mrgctx);
+
+ if (index < size - 1)
+ break;
+ index -= size - 1;
+ }
+
+ NEW_BBLOCK (cfg, end_bb);
+ NEW_BBLOCK (cfg, is_null_bb);
+
+ if (mrgctx) {
+ rgctx_reg = rgctx->dreg;
+ } else {
+ rgctx_reg = alloc_preg (cfg);
+
+ MONO_EMIT_NEW_LOAD_MEMBASE (cfg, rgctx_reg, rgctx->dreg, MONO_STRUCT_OFFSET (MonoVTable, runtime_generic_context));
+ // FIXME: Avoid this check by allocating the table when the vtable is created etc.
+ NEW_BBLOCK (cfg, is_null_bb);
+
+ MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, rgctx_reg, 0);
+ MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, is_null_bb);
+ }
+
+ for (i = 0; i < depth; ++i) {
+ int array_reg = alloc_preg (cfg);
+
+ /* load ptr to next array */
+ if (mrgctx && i == 0)
+ MONO_EMIT_NEW_LOAD_MEMBASE (cfg, array_reg, rgctx_reg, MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT);
+ else
+ MONO_EMIT_NEW_LOAD_MEMBASE (cfg, array_reg, rgctx_reg, 0);
+ rgctx_reg = array_reg;
+ /* is the ptr null? */
+ MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, rgctx_reg, 0);
+ /* if yes, jump to actual trampoline */
+ MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, is_null_bb);
+ }
+
+ /* fetch slot */
+ val_reg = alloc_preg (cfg);
+ MONO_EMIT_NEW_LOAD_MEMBASE (cfg, val_reg, rgctx_reg, (index + 1) * sizeof (gpointer));
+ /* is the slot null? */
+ MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, val_reg, 0);
+ /* if yes, jump to actual trampoline */
+ MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, is_null_bb);
+
+ /* Fastpath */
+ res_reg = alloc_preg (cfg);
+ MONO_INST_NEW (cfg, ins, OP_MOVE);
+ ins->dreg = res_reg;
+ ins->sreg1 = val_reg;
+ MONO_ADD_INS (cfg->cbb, ins);
+ res = ins;
+ MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
+
+ /* Slowpath */
+ MONO_START_BB (cfg, is_null_bb);
+ args [0] = rgctx;
+ EMIT_NEW_ICONST (cfg, args [1], index);
+ if (mrgctx)
+ call = mono_emit_jit_icall (cfg, mono_fill_method_rgctx, args);
+ else
+ call = mono_emit_jit_icall (cfg, mono_fill_class_rgctx, args);
+ MONO_INST_NEW (cfg, ins, OP_MOVE);
+ ins->dreg = res_reg;
+ ins->sreg1 = call->dreg;
+ MONO_ADD_INS (cfg->cbb, ins);
+ MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
+
+ MONO_START_BB (cfg, end_bb);
+
+ return res;
+#else