[runtime] Refactor and unify tls access
[mono.git] / mono / mini / mini-amd64.c
index b9a4503e2e2be0cbcff3491c925192b0463c21b6..25d0b8c977d4786708a83a47e585fdf2b56b6afb 100644 (file)
@@ -339,39 +339,6 @@ merge_argument_class_from_type (MonoType *type, ArgumentClass class1)
        return class1;
 }
 
-static int
-count_fields_nested (MonoClass *klass, gboolean pinvoke)
-{
-       MonoMarshalType *info;
-       int i, count;
-
-       count = 0;
-       if (pinvoke) {
-               info = mono_marshal_load_type_info (klass);
-               g_assert(info);
-               for (i = 0; i < info->num_fields; ++i) {
-                       if (MONO_TYPE_ISSTRUCT (info->fields [i].field->type))
-                               count += count_fields_nested (mono_class_from_mono_type (info->fields [i].field->type), pinvoke);
-                       else
-                               count ++;
-               }
-       } else {
-               gpointer iter;
-               MonoClassField *field;
-
-               iter = NULL;
-               while ((field = mono_class_get_fields (klass, &iter))) {
-                       if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
-                               continue;
-                       if (MONO_TYPE_ISSTRUCT (field->type))
-                               count += count_fields_nested (mono_class_from_mono_type (field->type), pinvoke);
-                       else
-                               count ++;
-               }
-       }
-       return count;
-}
-
 typedef struct {
        MonoType *type;
        int size, offset;
@@ -382,8 +349,8 @@ typedef struct {
  *
  *   Collect field info from KLASS recursively into FIELDS.
  */
-static int
-collect_field_info_nested (MonoClass *klass, StructFieldInfo *fields, int index, int offset, gboolean pinvoke, gboolean unicode)
+static void
+collect_field_info_nested (MonoClass *klass, GArray *fields_array, int offset, gboolean pinvoke, gboolean unicode)
 {
        MonoMarshalType *info;
        int i;
@@ -393,20 +360,32 @@ collect_field_info_nested (MonoClass *klass, StructFieldInfo *fields, int index,
                g_assert(info);
                for (i = 0; i < info->num_fields; ++i) {
                        if (MONO_TYPE_ISSTRUCT (info->fields [i].field->type)) {
-                               index = collect_field_info_nested (mono_class_from_mono_type (info->fields [i].field->type), fields, index, info->fields [i].offset, pinvoke, unicode);
+                               collect_field_info_nested (mono_class_from_mono_type (info->fields [i].field->type), fields_array, info->fields [i].offset, pinvoke, unicode);
                        } else {
                                guint32 align;
+                               StructFieldInfo f;
 
-                               fields [index].type = info->fields [i].field->type;
-                               fields [index].size = mono_marshal_type_size (info->fields [i].field->type,
+                               f.type = info->fields [i].field->type;
+                               f.size = mono_marshal_type_size (info->fields [i].field->type,
                                                                                                                           info->fields [i].mspec,
                                                                                                                           &align, TRUE, unicode);
-                               fields [index].offset = offset + info->fields [i].offset;
-                               if (i == info->num_fields - 1 && fields [index].size + fields [index].offset < info->native_size) {
+                               f.offset = offset + info->fields [i].offset;
+                               if (i == info->num_fields - 1 && f.size + f.offset < info->native_size) {
                                        /* This can happen with .pack directives eg. 'fixed' arrays */
-                                       fields [index].size = info->native_size - fields [index].offset;
+                                       if (MONO_TYPE_IS_PRIMITIVE (f.type)) {
+                                               /* Replicate the last field to fill out the remaining place, since the code in add_valuetype () needs type information */
+                                               g_array_append_val (fields_array, f);
+                                               while (f.size + f.offset < info->native_size) {
+                                                       f.offset += f.size;
+                                                       g_array_append_val (fields_array, f);
+                                               }
+                                       } else {
+                                               f.size = info->native_size - f.offset;
+                                               g_array_append_val (fields_array, f);
+                                       }
+                               } else {
+                                       g_array_append_val (fields_array, f);
                                }
-                               index ++;
                        }
                }
        } else {
@@ -418,18 +397,19 @@ collect_field_info_nested (MonoClass *klass, StructFieldInfo *fields, int index,
                        if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
                                continue;
                        if (MONO_TYPE_ISSTRUCT (field->type)) {
-                               index = collect_field_info_nested (mono_class_from_mono_type (field->type), fields, index, field->offset - sizeof (MonoObject), pinvoke, unicode);
+                               collect_field_info_nested (mono_class_from_mono_type (field->type), fields_array, field->offset - sizeof (MonoObject), pinvoke, unicode);
                        } else {
                                int align;
+                               StructFieldInfo f;
+
+                               f.type = field->type;
+                               f.size = mono_type_size (field->type, &align);
+                               f.offset = field->offset - sizeof (MonoObject) + offset;
 
-                               fields [index].type = field->type;
-                               fields [index].size = mono_type_size (field->type, &align);
-                               fields [index].offset = field->offset - sizeof (MonoObject) + offset;
-                               index ++;
+                               g_array_append_val (fields_array, f);
                        }
                }
        }
-       return index;
 }
 
 #ifdef TARGET_WIN32
@@ -650,6 +630,7 @@ add_valuetype (MonoMethodSignature *sig, ArgInfo *ainfo, MonoType *type,
        guint32 quadsize [2] = {8, 8};
        ArgumentClass args [2];
        StructFieldInfo *fields = NULL;
+       GArray *fields_array;
        MonoClass *klass;
        gboolean pass_on_stack = FALSE;
        int struct_size;
@@ -676,9 +657,10 @@ add_valuetype (MonoMethodSignature *sig, ArgInfo *ainfo, MonoType *type,
         * Collect field information recursively to be able to
         * handle nested structures.
         */
-       nfields = count_fields_nested (klass, sig->pinvoke);
-       fields = g_new0 (StructFieldInfo, nfields);
-       collect_field_info_nested (klass, fields, 0, 0, sig->pinvoke, klass->unicode);
+       fields_array = g_array_new (FALSE, TRUE, sizeof (StructFieldInfo));
+       collect_field_info_nested (klass, fields_array, 0, sig->pinvoke, klass->unicode);
+       fields = (StructFieldInfo*)fields_array->data;
+       nfields = fields_array->len;
 
        for (i = 0; i < nfields; ++i) {
                if ((fields [i].offset < 8) && (fields [i].offset + fields [i].size) > 8) {
@@ -701,7 +683,7 @@ add_valuetype (MonoMethodSignature *sig, ArgInfo *ainfo, MonoType *type,
                if (!is_return)
                        ainfo->arg_size = ALIGN_TO (size, 8);
 
-               g_free (fields);
+               g_array_free (fields_array, TRUE);
                return;
        }
 
@@ -743,7 +725,7 @@ add_valuetype (MonoMethodSignature *sig, ArgInfo *ainfo, MonoType *type,
                        if (!is_return)
                                ainfo->arg_size = ALIGN_TO (struct_size, 8);
 
-                       g_free (fields);
+                       g_array_free (fields_array, TRUE);
                        return;
                }
 
@@ -781,7 +763,7 @@ add_valuetype (MonoMethodSignature *sig, ArgInfo *ainfo, MonoType *type,
                }
        }
 
-       g_free (fields);
+       g_array_free (fields_array, TRUE);
 
        /* Post merger cleanup */
        if ((args [0] == ARG_CLASS_MEMORY) || (args [1] == ARG_CLASS_MEMORY))
@@ -1842,7 +1824,7 @@ mono_arch_create_vars (MonoCompile *cfg)
        if (cfg->method->save_lmf) {
                cfg->lmf_ir = TRUE;
 #if !defined(TARGET_WIN32)
-               if (mono_get_lmf_tls_offset () != -1 && !optimize_for_xen)
+               if (!optimize_for_xen)
                        cfg->lmf_ir_mono_lmf = TRUE;
 #endif
        }
@@ -3697,21 +3679,6 @@ amd64_emit_tls_set_reg (guint8 *code, int sreg, int offset_reg)
        return code;
 }
  
- /*
- * mono_arch_translate_tls_offset:
- *
- *   Translate the TLS offset OFFSET computed by MONO_THREAD_VAR_OFFSET () into a format usable by OP_TLS_GET_REG/OP_TLS_SET_REG.
- */
-int
-mono_arch_translate_tls_offset (int offset)
-{
-#ifdef __APPLE__
-       return tls_gs_offset + (offset * 8);
-#else
-       return offset;
-#endif
-}
-
 /*
  * emit_setup_lmf:
  *
@@ -4901,16 +4868,11 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        break;
                }
                case OP_GENERIC_CLASS_INIT: {
-                       static int byte_offset = -1;
-                       static guint8 bitmask;
                        guint8 *jump;
 
                        g_assert (ins->sreg1 == MONO_AMD64_ARG_REG1);
 
-                       if (byte_offset < 0)
-                               mono_marshal_find_bitfield_offset (MonoVTable, initialized, &byte_offset, &bitmask);
-
-                       amd64_test_membase_imm_size (code, ins->sreg1, byte_offset, bitmask, 1);
+                       amd64_test_membase_imm_size (code, ins->sreg1, MONO_STRUCT_OFFSET (MonoVTable, initialized), 1, 1);
                        jump = code;
                        amd64_branch8 (code, X86_CC_NZ, -1, 1);
 
@@ -6517,8 +6479,12 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_XZERO:
                        amd64_sse_pxor_reg_reg (code, ins->dreg, ins->dreg);
                        break;
+               case OP_XONES:
+                       amd64_sse_pcmpeqb_reg_reg (code, ins->dreg, ins->dreg);
+                       break;
                case OP_ICONV_TO_R4_RAW:
                        amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
+                       amd64_sse_cvtss2sd_reg_reg (code, ins->dreg, ins->dreg);
                        break;
 
                case OP_FCONV_TO_R8_X:
@@ -7221,6 +7187,8 @@ mono_arch_emit_epilog (MonoCompile *cfg)
        
        if (method->save_lmf) {
                /* check if we need to restore protection of the stack after a stack overflow */
+               /* FIXME */
+#if 0
                if (!cfg->compile_aot && mono_get_jit_tls_offset () != -1) {
                        guint8 *patch;
                        code = mono_amd64_emit_tls_get (code, AMD64_RCX, mono_get_jit_tls_offset ());
@@ -7237,6 +7205,7 @@ mono_arch_emit_epilog (MonoCompile *cfg)
                } else {
                        /* FIXME: maybe save the jit tls in the prolog */
                }
+#endif
                if (cfg->used_int_regs & (1 << AMD64_RBP)) {
                        amd64_mov_reg_membase (code, AMD64_RBP, cfg->frame_reg, lmf_offset + MONO_STRUCT_OFFSET (MonoLMF, rbp), 8);
                }