From f493a4265f31b5b09ebe62254864fe12aa125ec7 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 24 Feb 2010 05:01:27 +0000 Subject: [PATCH] 2010-02-24 Zoltan Varga * method-to-ir.c (mono_method_to_ir): Implement AOT support for fast TLS access. svn path=/trunk/mono/; revision=152330 --- mono/mini/ChangeLog | 4 ++ mono/mini/method-to-ir.c | 82 ++++++++++++++++++++++++---------------- mono/mini/mini.c | 11 ++++++ 3 files changed, 64 insertions(+), 33 deletions(-) diff --git a/mono/mini/ChangeLog b/mono/mini/ChangeLog index cabddca6560..d6da8856219 100755 --- a/mono/mini/ChangeLog +++ b/mono/mini/ChangeLog @@ -1,3 +1,7 @@ +2010-02-24 Zoltan Varga + + * method-to-ir.c (mono_method_to_ir): Implement AOT support for fast TLS access. + 2010-02-24 Zoltan Varga * method-to-ir.c (mono_method_to_ir): Implement support for fast access to diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index 225b488e47a..efa9b06eed6 100644 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -8027,8 +8027,53 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b is_special_static = mono_class_field_is_special_static (field); /* Generate IR to compute the field address */ + if (is_special_static && ((gsize)addr & 0x80000000) == 0 && mono_get_thread_intrinsic (cfg) && !(cfg->opt & MONO_OPT_SHARED) && !context_used) { + /* + * Fast access to TLS data + * Inline version of get_thread_static_data () in + * threads.c. + */ + guint32 offset; + int idx, static_data_reg, array_reg, dreg; + MonoInst *thread_ins; + + // offset &= 0x7fffffff; + // idx = (offset >> 24) - 1; + // return ((char*) thread->static_data [idx]) + (offset & 0xffffff); + + thread_ins = mono_get_thread_intrinsic (cfg); + MONO_ADD_INS (cfg->cbb, thread_ins); + static_data_reg = alloc_ireg (cfg); + MONO_EMIT_NEW_LOAD_MEMBASE (cfg, static_data_reg, thread_ins->dreg, G_STRUCT_OFFSET (MonoInternalThread, static_data)); + + if (cfg->compile_aot) { + int offset_reg, offset2_reg, idx_reg; + + /* For TLS variables, this will return the TLS offset */ + 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); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHR_IMM, idx_reg, offset_reg, 24); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISUB_IMM, idx_reg, idx_reg, 1); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHL_IMM, idx_reg, idx_reg, sizeof (gpointer) == 8 ? 3 : 2); + MONO_EMIT_NEW_BIALU (cfg, OP_PADD, static_data_reg, static_data_reg, idx_reg); + array_reg = alloc_ireg (cfg); + MONO_EMIT_NEW_LOAD_MEMBASE (cfg, array_reg, static_data_reg, 0); + offset2_reg = alloc_ireg (cfg); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IAND_IMM, offset2_reg, offset_reg, 0xffffff); + dreg = alloc_ireg (cfg); + EMIT_NEW_BIALU (cfg, ins, OP_PADD, dreg, array_reg, offset2_reg); + } else { + offset = (gsize)addr & 0x7fffffff; + idx = (offset >> 24) - 1; - if ((cfg->opt & MONO_OPT_SHARED) || + array_reg = alloc_ireg (cfg); + MONO_EMIT_NEW_LOAD_MEMBASE (cfg, array_reg, static_data_reg, idx * sizeof (gpointer)); + dreg = alloc_ireg (cfg); + EMIT_NEW_BIALU_IMM (cfg, ins, OP_ADD_IMM, dreg, array_reg, (offset & 0xffffff)); + } + } else if ((cfg->opt & MONO_OPT_SHARED) || (cfg->compile_aot && is_special_static) || (context_used && is_special_static)) { MonoInst *iargs [2]; @@ -8127,38 +8172,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b else EMIT_NEW_PCONST (cfg, ins, addr); } else { - /* - * insert call to mono_threads_get_static_data (GPOINTER_TO_UINT (addr)) - * This could be later optimized to do just a couple of - * memory dereferences with constant offsets. - */ - if (!cfg->compile_aot && ((gsize)addr & 0x80000000) == 0 && mono_get_thread_intrinsic (cfg)) { - /* - * Fast access to TLS data - * Inline version of get_thread_static_data () in - * threads.c. - */ - guint32 offset; - int idx, static_data_reg, array_reg, dreg; - MonoInst *thread_ins; - - offset = (gsize)addr & 0x7fffffff; - idx = (offset >> 24) - 1; - - // return ((char*) thread->static_data [idx]) + (offset & 0xffffff); - thread_ins = mono_get_thread_intrinsic (cfg); - MONO_ADD_INS (cfg->cbb, thread_ins); - static_data_reg = alloc_ireg (cfg); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, static_data_reg, thread_ins->dreg, G_STRUCT_OFFSET (MonoInternalThread, static_data)); - array_reg = alloc_ireg (cfg); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, array_reg, static_data_reg, idx * sizeof (gpointer)); - dreg = alloc_ireg (cfg); - EMIT_NEW_BIALU_IMM (cfg, ins, OP_ADD_IMM, dreg, array_reg, (offset & 0xffffff)); - } else { - MonoInst *iargs [1]; - EMIT_NEW_ICONST (cfg, iargs [0], GPOINTER_TO_UINT (addr)); - ins = mono_emit_jit_icall (cfg, mono_get_special_static_data, iargs); - } + MonoInst *iargs [1]; + EMIT_NEW_ICONST (cfg, iargs [0], GPOINTER_TO_UINT (addr)); + ins = mono_emit_jit_icall (cfg, mono_get_special_static_data, iargs); } } diff --git a/mono/mini/mini.c b/mono/mini/mini.c index f977b3a66c4..a300ecd91f4 100644 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -2729,6 +2729,17 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code, case MONO_PATCH_INFO_SFLDA: { MonoVTable *vtable = mono_class_vtable (domain, patch_info->data.field->parent); + if (mono_class_field_is_special_static (patch_info->data.field)) { + gpointer addr; + + mono_domain_lock (domain); + if (domain->special_static_fields) + addr = g_hash_table_lookup (domain->special_static_fields, patch_info->data.field); + mono_domain_unlock (domain); + g_assert (addr); + return addr; + } + g_assert (vtable); if (!vtable->initialized && !(vtable->klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT) && (method && mono_class_needs_cctor_run (vtable->klass, method))) /* Done by the generated code */ -- 2.25.1