{
MonoInst *call;
- // FIXME: No fastpath since the slot is not a compile time constant
- MonoInst *args [2] = { rgctx };
- EMIT_NEW_AOTCONST (cfg, args [1], MONO_PATCH_INFO_RGCTX_SLOT_INDEX, entry);
- if (entry->in_mrgctx)
- call = mono_emit_jit_icall (cfg, mono_fill_method_rgctx, args);
- else
- call = mono_emit_jit_icall (cfg, mono_fill_class_rgctx, args);
- return call;
-#if 0
- /*
- * FIXME: This can be called during decompose, which is a problem since it creates
- * new bblocks.
- * Also, the fastpath doesn't work since the slot number is dynamically allocated.
- */
- 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 / TARGET_SIZEOF_VOID_P;
- for (depth = 0; ; ++depth) {
- int size = mono_class_rgctx_get_array_size (depth, mrgctx);
-
- if (index < size - 1)
- break;
- index -= size - 1;
+ MonoInst *slot_ins;
+ EMIT_NEW_AOTCONST (cfg, slot_ins, MONO_PATCH_INFO_RGCTX_SLOT_INDEX, entry);
+
+ // Can't add basic blocks during decompose/interp entry mode etc.
+ // FIXME: Add a fastpath for in_mrgctx
+ if (cfg->after_method_to_ir || cfg->gsharedvt || cfg->interp_entry_only || entry->in_mrgctx) {
+ MonoInst *args [2] = { rgctx, slot_ins };
+ if (entry->in_mrgctx)
+ call = mono_emit_jit_icall (cfg, mono_fill_method_rgctx, args);
+ else
+ call = mono_emit_jit_icall (cfg, mono_fill_class_rgctx, args);
+ return call;
}
- NEW_BBLOCK (cfg, end_bb);
- NEW_BBLOCK (cfg, is_null_bb);
+ MonoBasicBlock *slowpath_bb, *end_bb;
+ MonoInst *ins, *res;
+ int rgctx_reg, res_reg;
- if (mrgctx) {
- rgctx_reg = rgctx->dreg;
- } else {
- rgctx_reg = alloc_preg (cfg);
+ /*
+ * rgctx = vtable->runtime_generic_context;
+ * if (rgctx) {
+ * val = rgctx [slot + 1];
+ * if (val)
+ * return val;
+ * }
+ * <slowpath>
+ */
+ NEW_BBLOCK (cfg, end_bb);
+ NEW_BBLOCK (cfg, slowpath_bb);
- 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);
+ 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.
+ MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, rgctx_reg, 0);
+ MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, slowpath_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);
- }
+ int table_size = mono_class_rgctx_get_array_size (0, FALSE);
+ MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, slot_ins->dreg, table_size - 1);
+ MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBGE, slowpath_bb);
- for (i = 0; i < depth; ++i) {
- int array_reg = alloc_preg (cfg);
+ int shifted_slot_reg = alloc_ireg (cfg);
+ EMIT_NEW_BIALU_IMM (cfg, ins, OP_ISHL_IMM, shifted_slot_reg, slot_ins->dreg, TARGET_SIZEOF_VOID_P == 8 ? 3 : 2);
- /* 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);
- }
+ int addr_reg = alloc_preg (cfg);
+ EMIT_NEW_UNALU (cfg, ins, OP_MOVE, addr_reg, rgctx_reg);
+ EMIT_NEW_BIALU (cfg, ins, OP_PADD, addr_reg, addr_reg, shifted_slot_reg);
+ int val_reg = alloc_preg (cfg);
+ MONO_EMIT_NEW_LOAD_MEMBASE (cfg, val_reg, addr_reg, TARGET_SIZEOF_VOID_P);
- /* fetch slot */
- val_reg = alloc_preg (cfg);
- MONO_EMIT_NEW_LOAD_MEMBASE (cfg, val_reg, rgctx_reg, (index + 1) * TARGET_SIZEOF_VOID_P);
- /* 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);
+ MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, slowpath_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);
+ EMIT_NEW_UNALU (cfg, ins, OP_MOVE, res_reg, val_reg);
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_START_BB (cfg, slowpath_bb);
+ slowpath_bb->out_of_line = TRUE;
+
+ MonoInst *args[2] = { rgctx, slot_ins };
+ call = mono_emit_jit_icall (cfg, mono_fill_class_rgctx, args);
+ EMIT_NEW_UNALU (cfg, ins, OP_MOVE, res_reg, call->dreg);
MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
MONO_START_BB (cfg, end_bb);
return res;
-#endif
}
/*