NEW_BBLOCK (cfg, is_nullable_bb);
NEW_BBLOCK (cfg, end_bb);
is_ref = emit_get_gsharedvt_info_klass (cfg, klass, MONO_RGCTX_INFO_CLASS_BOX_TYPE);
- MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, is_ref->dreg, 1);
+ MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, is_ref->dreg, MONO_GSHAREDVT_BOX_TYPE_REF);
MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBEQ, is_ref_bb);
- MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, is_ref->dreg, 2);
+ MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, is_ref->dreg, MONO_GSHAREDVT_BOX_TYPE_NULLABLE);
MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBEQ, is_nullable_bb);
/* This will contain either the address of the unboxed vtype, or an address of the temporary where the ref is stored */
NEW_BBLOCK (cfg, is_nullable_bb);
NEW_BBLOCK (cfg, end_bb);
is_ref = emit_get_gsharedvt_info_klass (cfg, klass, MONO_RGCTX_INFO_CLASS_BOX_TYPE);
- MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, is_ref->dreg, 1);
+ MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, is_ref->dreg, MONO_GSHAREDVT_BOX_TYPE_REF);
MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBEQ, is_ref_bb);
- MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, is_ref->dreg, 2);
+ MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, is_ref->dreg, MONO_GSHAREDVT_BOX_TYPE_NULLABLE);
MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBEQ, is_nullable_bb);
/* Non-ref case */
args [4] = ins;
if (mini_is_gsharedvt_type (fsig->params [0])) {
- int addr_reg;
+ int addr_reg, deref_arg_reg;
- args [3] = emit_get_gsharedvt_info_klass (cfg, mono_class_from_mono_type (fsig->params [0]), MONO_RGCTX_INFO_CLASS_BOX_TYPE);
+ ins = emit_get_gsharedvt_info_klass (cfg, mono_class_from_mono_type (fsig->params [0]), MONO_RGCTX_INFO_CLASS_BOX_TYPE);
+ deref_arg_reg = alloc_preg (cfg);
+ /* deref_arg = BOX_TYPE != MONO_GSHAREDVT_BOX_TYPE_VTYPE */
+ EMIT_NEW_BIALU_IMM (cfg, args [3], OP_ISUB_IMM, deref_arg_reg, ins->dreg, 1);
EMIT_NEW_VARLOADA_VREG (cfg, ins, sp [1]->dreg, fsig->params [0]);
addr_reg = ins->dreg;
NEW_BBLOCK (cfg, end_bb);
box_type = emit_get_rgctx_virt_method (cfg, mono_class_check_context_used (constrained_class), constrained_class, cmethod, MONO_RGCTX_INFO_VIRT_METHOD_BOX_TYPE);
- MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, box_type->dreg, 1);
+ MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, box_type->dreg, MONO_GSHAREDVT_BOX_TYPE_REF);
MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBEQ, is_ref_bb);
/* Non-ref case */
context_used = mini_class_check_context_used (cfg, klass);
offset_ins = emit_get_gsharedvt_info (cfg, field, MONO_RGCTX_INFO_FIELD_OFFSET);
+ /* The value is offset by 1 */
+ EMIT_NEW_BIALU_IMM (cfg, ins, OP_PSUB_IMM, offset_ins->dreg, offset_ins->dreg, 1);
dreg = alloc_ireg_mp (cfg);
EMIT_NEW_BIALU (cfg, ins, OP_PADD, dreg, sp [0]->dreg, offset_ins->dreg);
/* The decomposition will call mini_emit_stobj () which will emit a wbarrier if needed */
MonoInst *offset_ins;
offset_ins = emit_get_gsharedvt_info (cfg, field, MONO_RGCTX_INFO_FIELD_OFFSET);
+ /* The value is offset by 1 */
+ EMIT_NEW_BIALU_IMM (cfg, ins, OP_PSUB_IMM, offset_ins->dreg, offset_ins->dreg, 1);
EMIT_NEW_BIALU (cfg, ins, OP_PADD, dreg, sp [0]->dreg, offset_ins->dreg);
} else {
EMIT_NEW_BIALU_IMM (cfg, ins, OP_PADD_IMM, dreg, sp [0]->dreg, foffset);
MonoInst *offset_ins;
offset_ins = emit_get_gsharedvt_info (cfg, field, MONO_RGCTX_INFO_FIELD_OFFSET);
+ /* The value is offset by 1 */
+ EMIT_NEW_BIALU_IMM (cfg, ins, OP_PSUB_IMM, offset_ins->dreg, offset_ins->dreg, 1);
dreg = alloc_ireg_mp (cfg);
EMIT_NEW_BIALU (cfg, ins, OP_PADD, dreg, sp [0]->dreg, offset_ins->dreg);
EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, load, field->type, dreg, 0);
MonoInst *offset_ins;
offset_ins = emit_get_rgctx_field (cfg, context_used, field, MONO_RGCTX_INFO_FIELD_OFFSET);
+ /* The value is offset by 1 */
+ EMIT_NEW_BIALU_IMM (cfg, ins, OP_PSUB_IMM, offset_ins->dreg, offset_ins->dreg, 1);
dreg = alloc_ireg_mp (cfg);
EMIT_NEW_BIALU (cfg, ins, OP_PADD, dreg, static_data->dreg, offset_ins->dreg);
} else if (field->offset == 0) {
return GUINT_TO_POINTER (mono_class_value_size (klass, NULL));
case MONO_RGCTX_INFO_CLASS_BOX_TYPE:
if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg))
- return GUINT_TO_POINTER (1);
+ return GUINT_TO_POINTER (MONO_GSHAREDVT_BOX_TYPE_REF);
else if (mono_class_is_nullable (klass))
- return GUINT_TO_POINTER (2);
+ return GUINT_TO_POINTER (MONO_GSHAREDVT_BOX_TYPE_NULLABLE);
else
- return GUINT_TO_POINTER (0);
+ return GUINT_TO_POINTER (MONO_GSHAREDVT_BOX_TYPE_VTYPE);
case MONO_RGCTX_INFO_MEMCPY:
case MONO_RGCTX_INFO_BZERO: {
static MonoMethod *memcpy_method [17];
impl_class = method->klass;
if (MONO_TYPE_IS_REFERENCE (&impl_class->byval_arg))
- return GUINT_TO_POINTER (1);
+ return GUINT_TO_POINTER (MONO_GSHAREDVT_BOX_TYPE_REF);
else if (mono_class_is_nullable (impl_class))
- return GUINT_TO_POINTER (2);
+ return GUINT_TO_POINTER (MONO_GSHAREDVT_BOX_TYPE_NULLABLE);
else
- return GUINT_TO_POINTER (0);
+ return GUINT_TO_POINTER (MONO_GSHAREDVT_BOX_TYPE_VTYPE);
}
#ifndef DISABLE_REMOTING
case MONO_RGCTX_INFO_REMOTING_INVOKE_WITH_CHECK:
case MONO_RGCTX_INFO_FIELD_OFFSET: {
MonoClassField *field = data;
+ /* The value is offset by 1 */
if (field->parent->valuetype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
- return GUINT_TO_POINTER (field->offset - sizeof (MonoObject));
+ return GUINT_TO_POINTER (field->offset - sizeof (MonoObject) + 1);
else
- return GUINT_TO_POINTER (field->offset);
+ return GUINT_TO_POINTER (field->offset + 1);
}
case MONO_RGCTX_INFO_METHOD_RGCTX: {
MonoMethodInflated *method = data;
method_inst ? method_inst->type_argc : 0, slot, TRUE, TRUE, &do_free);
/* This might take the loader lock */
info = instantiate_info (domain, &oti, &context, klass);
+ g_assert (info);
/*
if (method_inst)
MONO_GENERIC_CONTEXT_USED_METHOD = 2
};
+enum {
+ /* Cannot be 0 since this is stored in rgctx slots, and 0 means an unitialized rgctx slot */
+ MONO_GSHAREDVT_BOX_TYPE_VTYPE = 1,
+ MONO_GSHAREDVT_BOX_TYPE_REF = 2,
+ MONO_GSHAREDVT_BOX_TYPE_NULLABLE = 3
+};
+
typedef enum {
MONO_RGCTX_INFO_STATIC_DATA,
MONO_RGCTX_INFO_KLASS,
MONO_RGCTX_INFO_CAST_CACHE,
MONO_RGCTX_INFO_ARRAY_ELEMENT_SIZE,
MONO_RGCTX_INFO_VALUE_SIZE,
+ /* +1 to avoid zero values in rgctx slots */
MONO_RGCTX_INFO_FIELD_OFFSET,
/* Either the code for a gsharedvt method, or the address for a gsharedvt-out trampoline for the method */
MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE,
MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE_VIRT,
/* Same for calli, associated with a signature */
MONO_RGCTX_INFO_SIG_GSHAREDVT_OUT_TRAMPOLINE_CALLI,
- /*
- * 0 - vtype
- * 1 - ref
- * 2 - gsharedvt type
- */
+ /* One of MONO_GSHAREDVT_BOX_TYPE */
MONO_RGCTX_INFO_CLASS_BOX_TYPE,
/* Resolves to a MonoGSharedVtMethodRuntimeInfo */
MONO_RGCTX_INFO_METHOD_GSHAREDVT_INFO,
#define OP_DUMMY_PCONST OP_DUMMY_I8CONST
#define OP_PADD OP_LADD
#define OP_PADD_IMM OP_LADD_IMM
+#define OP_PSUB_IMM OP_LSUB_IMM
#define OP_PAND_IMM OP_LAND_IMM
#define OP_PSUB OP_LSUB
#define OP_PMUL OP_LMUL
#define OP_DUMMY_PCONST OP_DUMMY_ICONST
#define OP_PADD OP_IADD
#define OP_PADD_IMM OP_IADD_IMM
+#define OP_PSUB_IMM OP_ISUB_IMM
#define OP_PAND_IMM OP_IAND_IMM
#define OP_PSUB OP_ISUB
#define OP_PMUL OP_IMUL