+
+static gboolean
+generic_class_is_reference_type (MonoCompile *cfg, MonoClass *klass)
+{
+ return mini_type_is_reference (cfg, &klass->byval_arg);
+}
+
+static MonoInst*
+emit_array_store (MonoCompile *cfg, MonoClass *klass, MonoInst **sp, gboolean safety_checks)
+{
+ if (safety_checks && generic_class_is_reference_type (cfg, klass) &&
+ !(sp [2]->opcode == OP_PCONST && sp [2]->inst_p0 == NULL)) {
+ MonoClass *obj_array = mono_array_class_get_cached (mono_defaults.object_class, 1);
+ MonoMethod *helper = mono_marshal_get_virtual_stelemref (obj_array);
+ MonoInst *iargs [3];
+
+ if (!helper->slot)
+ mono_class_setup_vtable (obj_array);
+ g_assert (helper->slot);
+
+ if (sp [0]->type != STACK_OBJ)
+ return NULL;
+ if (sp [2]->type != STACK_OBJ)
+ return NULL;
+
+ iargs [2] = sp [2];
+ iargs [1] = sp [1];
+ iargs [0] = sp [0];
+
+ return mono_emit_method_call (cfg, helper, iargs, sp [0]);
+ } else {
+ MonoInst *ins;
+ if (sp [1]->opcode == OP_ICONST) {
+ int array_reg = sp [0]->dreg;
+ int index_reg = sp [1]->dreg;
+ int offset = (mono_class_array_element_size (klass) * sp [1]->inst_c0) + G_STRUCT_OFFSET (MonoArray, vector);
+
+ if (safety_checks)
+ MONO_EMIT_BOUNDS_CHECK (cfg, array_reg, MonoArray, max_length, index_reg);
+ EMIT_NEW_STORE_MEMBASE_TYPE (cfg, ins, &klass->byval_arg, array_reg, offset, sp [2]->dreg);
+ } else {
+ MonoInst *addr = mini_emit_ldelema_1_ins (cfg, klass, sp [0], sp [1], safety_checks);
+ EMIT_NEW_STORE_MEMBASE_TYPE (cfg, ins, &klass->byval_arg, addr->dreg, 0, sp [2]->dreg);
+ if (generic_class_is_reference_type (cfg, klass))
+ emit_write_barrier (cfg, addr, sp [2], -1);
+ }
+ return ins;
+ }
+}
+
+static MonoInst*
+emit_array_unsafe_access (MonoCompile *cfg, MonoMethodSignature *fsig, MonoInst **args, int is_set)
+{
+ MonoClass *eklass;
+
+ if (is_set)
+ eklass = mono_class_from_mono_type (fsig->params [2]);
+ else
+ eklass = mono_class_from_mono_type (fsig->ret);
+
+
+ if (is_set) {
+ return emit_array_store (cfg, eklass, args, FALSE);
+ } else {
+ MonoInst *ins, *addr = mini_emit_ldelema_1_ins (cfg, eklass, args [0], args [1], FALSE);
+ EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, &eklass->byval_arg, addr->dreg, 0);
+ return ins;
+ }
+}
+