From 99db20f0bcf62c860f959cfed34bc29945fa3929 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 8 Jan 2020 13:32:52 +0100 Subject: [PATCH] [jit] Implement fast TLS access in gshared methods. (mono/mono#18377) Fixes https://github.com/mono/mono/issues/18370. Commit migrated from https://github.com/mono/mono/commit/e999846088bb4b05b2fa22234bd70fb42fd02a80 --- src/mono/mono/mini/generics.cs | 22 ++++++++++++++++++++++ src/mono/mono/mini/method-to-ir.c | 16 ++++++++++------ src/mono/mono/mini/mini-generic-sharing.c | 15 +++++++++++++++ 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/src/mono/mono/mini/generics.cs b/src/mono/mono/mini/generics.cs index 857ad44..0c6346c 100644 --- a/src/mono/mono/mini/generics.cs +++ b/src/mono/mono/mini/generics.cs @@ -1462,6 +1462,28 @@ class Tests var t = FromResult>(new OneThing {Item1 = 42}); return t.Item1; } + + class ThreadLocalClass { + [ThreadStatic] + static T v; + + public T Value { + [MethodImpl (MethodImplOptions.NoInlining)] + get { + return v; + } + [MethodImpl (MethodImplOptions.NoInlining)] + set { + v = value; + } + } + } + + public static int test_0_tls_gshared () { + var c = new ThreadLocalClass (); + c.Value = "FOO"; + return c.Value == "FOO" ? 0 : 1; + } } #if !__MOBILE__ diff --git a/src/mono/mono/mini/method-to-ir.c b/src/mono/mono/mini/method-to-ir.c index 5334e10..606655a 100644 --- a/src/mono/mono/mini/method-to-ir.c +++ b/src/mono/mono/mini/method-to-ir.c @@ -9385,7 +9385,8 @@ calli_end: thread_ins = NULL; /* Generate IR to compute the field address */ - if (is_special_static && ((gsize)addr & 0x80000000) == 0 && thread_ins && !(cfg->opt & MONO_OPT_SHARED) && !context_used) { + if (is_special_static && ((gsize)addr & 0x80000000) == 0 && thread_ins && !(cfg->opt & MONO_OPT_SHARED) && + !(context_used && cfg->gsharedvt && mini_is_gsharedvt_klass (klass))) { /* * Fast access to TLS data * Inline version of get_thread_static_data () in @@ -9394,17 +9395,20 @@ calli_end: guint32 offset; int idx, static_data_reg, array_reg, dreg; - if (context_used && cfg->gsharedvt && mini_is_gsharedvt_klass (klass)) - GSHAREDVT_FAILURE (il_op); - static_data_reg = alloc_ireg (cfg); MONO_EMIT_NEW_LOAD_MEMBASE (cfg, static_data_reg, thread_ins->dreg, MONO_STRUCT_OFFSET (MonoInternalThread, static_data)); - if (cfg->compile_aot) { + if (cfg->compile_aot || context_used) { int offset_reg, offset2_reg, idx_reg; /* For TLS variables, this will return the TLS offset */ - EMIT_NEW_SFLDACONST (cfg, ins, field); + if (context_used) { + MonoInst *addr_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, addr_ins->dreg, addr_ins->dreg, 1); + } else { + EMIT_NEW_SFLDACONST (cfg, ins, field); + } offset_reg = ins->dreg; MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IAND_IMM, offset_reg, offset_reg, 0x7fffffff); idx_reg = alloc_ireg (cfg); diff --git a/src/mono/mono/mini/mini-generic-sharing.c b/src/mono/mono/mini/mini-generic-sharing.c index 279fbaf..5ee4434 100644 --- a/src/mono/mono/mini/mini-generic-sharing.c +++ b/src/mono/mono/mini/mini-generic-sharing.c @@ -2255,6 +2255,21 @@ instantiate_info (MonoDomain *domain, MonoRuntimeGenericContextInfoTemplate *oti case MONO_RGCTX_INFO_FIELD_OFFSET: { MonoClassField *field = (MonoClassField *)data; + if (mono_class_field_is_special_static (field)) { + gpointer addr; + + mono_class_vtable_checked (domain, klass, error); + mono_error_assert_ok (error); + + /* Return the TLS offset */ + g_assert (domain->special_static_fields); + mono_domain_lock (domain); + addr = g_hash_table_lookup (domain->special_static_fields, field); + mono_domain_unlock (domain); + g_assert (addr); + return (guint8*)addr + 1; + } + /* The value is offset by 1 */ if (m_class_is_valuetype (field->parent) && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) return GUINT_TO_POINTER (field->offset - MONO_ABI_SIZEOF (MonoObject) + 1); -- 2.7.4