diff options
author | monojenkins <jo.shields+jenkins@xamarin.com> | 2018-10-10 20:25:41 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-10-10 20:25:41 +0300 |
commit | fb7ad92db918b2a217e4f21f8f46246a701ce8b0 (patch) | |
tree | d1729019ffb45e222711098b1335d92d9473ce99 | |
parent | 61613246290ab634a02ba56c22b0d809f840fa0a (diff) | |
parent | 78455914e8ef1b1a871a134081a7e25f975727c5 (diff) |
Merge pull request #11053 from BrzVlad/fix-interp-static-field
[interp] Optimize static field access
Do most of the work on transform side and include the field address in the instruction stream. We need to run cctor at runtime to preserve expected order. This makes static field access 4 times faster.
<!--
Thank you for your Pull Request!
If you are new to contributing to Mono, please try to do your best at conforming to our coding guidelines http://www.mono-project.com/community/contributing/coding-guidelines/ but don't worry if you get something wrong. One of the project members will help you to get things landed.
Does your pull request fix any of the existing issues? Please use the following format: Fixes #issue-number
-->
-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; |