2010-02-24 Zoltan Varga <vargaz@gmail.com>
authorZoltan Varga <vargaz@gmail.com>
Wed, 24 Feb 2010 05:01:27 +0000 (05:01 -0000)
committerZoltan Varga <vargaz@gmail.com>
Wed, 24 Feb 2010 05:01:27 +0000 (05:01 -0000)
* method-to-ir.c (mono_method_to_ir): Implement AOT support for fast TLS access.

svn path=/trunk/mono/; revision=152330

mono/mini/ChangeLog
mono/mini/method-to-ir.c
mono/mini/mini.c

index cabddca656084b1088993aa717bf16fd3199ad92..d6da885621989e6890bcce9e8307c2cb54833957 100755 (executable)
@@ -1,3 +1,7 @@
+2010-02-24  Zoltan Varga  <vargaz@gmail.com>
+
+       * method-to-ir.c (mono_method_to_ir): Implement AOT support for fast TLS access.
+
 2010-02-24  Zoltan Varga  <vargaz@gmail.com>
 
        * method-to-ir.c (mono_method_to_ir): Implement support for fast access to
index 225b488e47a068466d9a9105c54c4208b84d2984..efa9b06eed67f50ba7d1143e43ebc4f57680db99 100644 (file)
@@ -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);
                                }
                        }
 
index f977b3a66c49caba9ae20bb4d015f0327c9b0121..a300ecd91f49e6ab3feb8d67c6ade7b212573c29 100644 (file)
@@ -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 */