diff options
-rw-r--r-- | mono/mini/interp/interp.c | 49 | ||||
-rw-r--r-- | mono/mini/interp/mintops.def | 21 | ||||
-rw-r--r-- | mono/mini/interp/transform.c | 32 |
3 files changed, 98 insertions, 4 deletions
diff --git a/mono/mini/interp/interp.c b/mono/mini/interp/interp.c index 02526ec2705..2c2ab929eba 100644 --- a/mono/mini/interp/interp.c +++ b/mono/mini/interp/interp.c @@ -4468,6 +4468,31 @@ interp_exec_method_full (InterpFrame *frame, ThreadContext *context, guint16 *st ++sp; MINT_IN_BREAK; } + +/* We init class here to preserve cctor order */ +#define LDSFLD(datamem, fieldtype) { \ + MonoVTable *vtable = (MonoVTable*) rtm->data_items [*(guint16*)(ip + 1)]; \ + if (G_UNLIKELY (!vtable->initialized)) { \ + mono_runtime_class_init_full (vtable, error); \ + if (!mono_error_ok (error)) \ + THROW_EX (mono_error_convert_to_exception (error), ip); \ + } \ + sp[0].data.datamem = * (fieldtype *)(rtm->data_items [* (guint16 *)(ip + 2)]) ; \ + ip += 3; \ + sp++; \ + } + + MINT_IN_CASE(MINT_LDSFLD_I1) LDSFLD(i, gint8); MINT_IN_BREAK; + MINT_IN_CASE(MINT_LDSFLD_U1) LDSFLD(i, guint8); MINT_IN_BREAK; + MINT_IN_CASE(MINT_LDSFLD_I2) LDSFLD(i, gint16); MINT_IN_BREAK; + MINT_IN_CASE(MINT_LDSFLD_U2) LDSFLD(i, guint16); MINT_IN_BREAK; + MINT_IN_CASE(MINT_LDSFLD_I4) LDSFLD(i, gint32); MINT_IN_BREAK; + MINT_IN_CASE(MINT_LDSFLD_I8) LDSFLD(l, gint64); MINT_IN_BREAK; + MINT_IN_CASE(MINT_LDSFLD_R4) LDSFLD(f_r4, float); MINT_IN_BREAK; + MINT_IN_CASE(MINT_LDSFLD_R8) LDSFLD(f, double); MINT_IN_BREAK; + MINT_IN_CASE(MINT_LDSFLD_O) LDSFLD(p, gpointer); MINT_IN_BREAK; + MINT_IN_CASE(MINT_LDSFLD_P) LDSFLD(p, gpointer); MINT_IN_BREAK; + MINT_IN_CASE(MINT_LDSFLD) { MonoClassField *field = (MonoClassField*)rtm->data_items [* (guint16 *)(ip + 1)]; gpointer addr = mono_class_static_field_address (rtm->domain, field); @@ -4490,6 +4515,30 @@ interp_exec_method_full (InterpFrame *frame, ThreadContext *context, guint16 *st ++sp; MINT_IN_BREAK; } + +#define STSFLD(datamem, fieldtype) { \ + MonoVTable *vtable = (MonoVTable*) rtm->data_items [*(guint16*)(ip + 1)]; \ + if (G_UNLIKELY (!vtable->initialized)) { \ + mono_runtime_class_init_full (vtable, error); \ + if (!mono_error_ok (error)) \ + THROW_EX (mono_error_convert_to_exception (error), ip); \ + } \ + sp --; \ + * (fieldtype *)(rtm->data_items [* (guint16 *)(ip + 2)]) = sp[0].data.datamem; \ + ip += 3; \ + } + + MINT_IN_CASE(MINT_STSFLD_I1) STSFLD(i, gint8); MINT_IN_BREAK; + MINT_IN_CASE(MINT_STSFLD_U1) STSFLD(i, guint8); MINT_IN_BREAK; + MINT_IN_CASE(MINT_STSFLD_I2) STSFLD(i, gint16); MINT_IN_BREAK; + MINT_IN_CASE(MINT_STSFLD_U2) STSFLD(i, guint16); MINT_IN_BREAK; + MINT_IN_CASE(MINT_STSFLD_I4) STSFLD(i, gint32); MINT_IN_BREAK; + MINT_IN_CASE(MINT_STSFLD_I8) STSFLD(l, gint64); MINT_IN_BREAK; + MINT_IN_CASE(MINT_STSFLD_R4) STSFLD(f_r4, float); MINT_IN_BREAK; + MINT_IN_CASE(MINT_STSFLD_R8) STSFLD(f, double); MINT_IN_BREAK; + MINT_IN_CASE(MINT_STSFLD_P) STSFLD(p, gpointer); MINT_IN_BREAK; + MINT_IN_CASE(MINT_STSFLD_O) STSFLD(p, gpointer); MINT_IN_BREAK; + MINT_IN_CASE(MINT_STSFLD) { MonoClassField *field = (MonoClassField*)rtm->data_items [* (guint16 *)(ip + 1)]; gpointer addr = mono_class_static_field_address (rtm->domain, field); diff --git a/mono/mini/interp/mintops.def b/mono/mini/interp/mintops.def index 21d16b2cfa8..33fca0240d6 100644 --- a/mono/mini/interp/mintops.def +++ b/mono/mini/interp/mintops.def @@ -114,8 +114,29 @@ OPDEF(MINT_STRMFLD, "strmfld", 2, MintOpFieldToken) OPDEF(MINT_STRMFLD_VT, "strmfld.vt", 2, MintOpUShortInt) OPDEF(MINT_LDSFLD, "ldsfld", 2, MintOpFieldToken) +OPDEF(MINT_LDSFLD_I1, "ldsfld.i1", 3, MintOpUShortInt) +OPDEF(MINT_LDSFLD_U1, "ldsfld.u1", 3, MintOpUShortInt) +OPDEF(MINT_LDSFLD_I2, "ldsfld.i2", 3, MintOpUShortInt) +OPDEF(MINT_LDSFLD_U2, "ldsfld.u2", 3, MintOpUShortInt) +OPDEF(MINT_LDSFLD_I4, "ldsfld.i4", 3, MintOpUShortInt) +OPDEF(MINT_LDSFLD_I8, "ldsfld.i8", 3, MintOpUShortInt) +OPDEF(MINT_LDSFLD_R4, "ldsfld.r4", 3, MintOpUShortInt) +OPDEF(MINT_LDSFLD_R8, "ldsfld.r8", 3, MintOpUShortInt) +OPDEF(MINT_LDSFLD_O, "ldsfld.o", 3, MintOpUShortInt) +OPDEF(MINT_LDSFLD_P, "ldsfld.p", 3, MintOpUShortInt) OPDEF(MINT_LDSFLD_VT, "ldsfld.vt", 4, MintOpShortAndInt) + OPDEF(MINT_STSFLD, "stsfld", 2, MintOpUShortInt) +OPDEF(MINT_STSFLD_I1, "stsfld.i1", 3, MintOpUShortInt) +OPDEF(MINT_STSFLD_U1, "stsfld.u1", 3, MintOpUShortInt) +OPDEF(MINT_STSFLD_I2, "stsfld.i2", 3, MintOpUShortInt) +OPDEF(MINT_STSFLD_U2, "stsfld.u2", 3, MintOpUShortInt) +OPDEF(MINT_STSFLD_I4, "stsfld.i4", 3, MintOpUShortInt) +OPDEF(MINT_STSFLD_I8, "stsfld.i8", 3, MintOpUShortInt) +OPDEF(MINT_STSFLD_R4, "stsfld.r4", 3, MintOpUShortInt) +OPDEF(MINT_STSFLD_R8, "stsfld.r8", 3, MintOpUShortInt) +OPDEF(MINT_STSFLD_O, "stsfld.o", 3, MintOpUShortInt) +OPDEF(MINT_STSFLD_P, "stsfld.p", 3, MintOpUShortInt) OPDEF(MINT_STSFLD_VT, "stsfld.vt", 2, MintOpUShortInt) OPDEF(MINT_LDSFLDA, "ldsflda", 2, MintOpUShortInt) diff --git a/mono/mini/interp/transform.c b/mono/mini/interp/transform.c index 8f7c9ac8959..6a336c99684 100644 --- a/mono/mini/interp/transform.c +++ b/mono/mini/interp/transform.c @@ -3636,15 +3636,26 @@ generate (MonoMethod *method, MonoMethodHeader *header, InterpMethod *rtm, unsig goto_if_nok (error, exit); MonoType *ftype = mono_field_get_type (field); mt = mint_type (ftype); - ADD_CODE(td, mt == MINT_TYPE_VT ? MINT_LDSFLD_VT : MINT_LDSFLD); - ADD_CODE(td, get_data_item_index (td, field)); klass = NULL; if (mt == MINT_TYPE_VT) { + ADD_CODE(td, MINT_LDSFLD_VT); + ADD_CODE(td, get_data_item_index (td, field)); klass = mono_class_from_mono_type (ftype); int size = mono_class_value_size (klass, NULL); PUSH_VT(td, size); WRITE32(td, &size); } else { + if (mono_class_field_is_special_static (field)) { + ADD_CODE(td, MINT_LDSFLD); + ADD_CODE(td, get_data_item_index (td, field)); + } else { + MonoVTable *vtable = mono_class_vtable_checked (domain, field->parent, error); + goto_if_nok (error, exit); + + ADD_CODE(td, MINT_LDSFLD_I1 + mt - MINT_TYPE_I1); + ADD_CODE(td, get_data_item_index (td, vtable)); + ADD_CODE(td, get_data_item_index (td, (char*)mono_vtable_get_static_field_data (vtable) + field->offset)); + } if (mt == MINT_TYPE_O) klass = mono_class_from_mono_type (ftype); } @@ -3659,8 +3670,6 @@ generate (MonoMethod *method, MonoMethodHeader *header, InterpMethod *rtm, unsig goto_if_nok (error, exit); MonoType *ftype = mono_field_get_type (field); mt = mint_type (ftype); - ADD_CODE(td, mt == MINT_TYPE_VT ? MINT_STSFLD_VT : MINT_STSFLD); - ADD_CODE(td, get_data_item_index (td, field)); /* the vtable of the field might not be initialized at this point */ MonoClass *fld_klass = mono_class_from_mono_type (field->type); @@ -3670,7 +3679,22 @@ generate (MonoMethod *method, MonoMethodHeader *header, InterpMethod *rtm, unsig if (mt == MINT_TYPE_VT) { MonoClass *klass = mono_class_from_mono_type (ftype); int size = mono_class_value_size (klass, NULL); + ADD_CODE(td, MINT_STSFLD_VT); + ADD_CODE(td, get_data_item_index (td, field)); POP_VT (td, size); + } else { + if (mono_class_field_is_special_static (field)) { + ADD_CODE(td, MINT_STSFLD); + ADD_CODE(td, get_data_item_index (td, field)); + } else { + MonoVTable *vtable = mono_class_vtable_checked (domain, field->parent, error); + goto_if_nok (error, exit); + + ADD_CODE(td, MINT_STSFLD_I1 + mt - MINT_TYPE_I1); + ADD_CODE(td, get_data_item_index (td, vtable)); + ADD_CODE(td, get_data_item_index (td, (char*)mono_vtable_get_static_field_data (vtable) + field->offset)); + } + } td->ip += 5; --td->sp; |