(root)/
gcc-13.2.0/
libobjc/
gc.c
       1  /* Basic data types for Objective C.
       2     Copyright (C) 1998-2023 Free Software Foundation, Inc.
       3     Contributed by Ovidiu Predescu.
       4  
       5  This file is part of GCC.
       6  
       7  GCC is free software; you can redistribute it and/or modify
       8  it under the terms of the GNU General Public License as published by
       9  the Free Software Foundation; either version 3, or (at your option)
      10  any later version.
      11  
      12  GCC is distributed in the hope that it will be useful,
      13  but WITHOUT ANY WARRANTY; without even the implied warranty of
      14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15  GNU General Public License for more details.
      16  
      17  Under Section 7 of GPL version 3, you are granted additional
      18  permissions described in the GCC Runtime Library Exception, version
      19  3.1, as published by the Free Software Foundation.
      20  
      21  You should have received a copy of the GNU General Public License and
      22  a copy of the GCC Runtime Library Exception along with this program;
      23  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
      24  <http://www.gnu.org/licenses/>.  */
      25  
      26  #include "objc-private/common.h"
      27  #include "objc/objc.h"
      28  
      29  #if OBJC_WITH_GC
      30  
      31  #include "tconfig.h"
      32  #include <assert.h>
      33  #include <ctype.h> /* For isdigit.  */
      34  #include <string.h>
      35  #include <stdlib.h>
      36  #include "objc/runtime.h"
      37  #include "objc-private/module-abi-8.h"
      38  
      39  #include <gc/gc.h>
      40  #include <limits.h>
      41  
      42  /* gc_typed.h uses the following but doesn't declare them */
      43  typedef GC_word word;
      44  typedef GC_signed_word signed_word;
      45  #define BITS_PER_WORD (CHAR_BIT * sizeof (word))
      46  
      47  #include <gc/gc_typed.h>
      48  
      49  /* The following functions set up in `mask` the corresponding pointers.
      50     The offset is incremented with the size of the type.  */
      51  
      52  #define ROUND(V, A) \
      53    ({ typeof (V) __v = (V); typeof (A) __a = (A); \
      54       __a * ((__v+__a - 1)/__a); })
      55  
      56  #define SET_BIT_FOR_OFFSET(mask, offset) \
      57    GC_set_bit (mask, offset / sizeof (void *))
      58  
      59  /* Some prototypes */
      60  static void
      61  __objc_gc_setup_struct (GC_bitmap mask, const char *type, int offset);
      62  static void
      63  __objc_gc_setup_union (GC_bitmap mask, const char *type, int offset);
      64  
      65  
      66  static void
      67  __objc_gc_setup_array (GC_bitmap mask, const char *type, int offset)
      68  {
      69    int i, len = atoi (type + 1);
      70  
      71    while (isdigit (*++type))
      72      /* do nothing */;		/* skip the size of the array */
      73  
      74    switch (*type) {
      75    case _C_ARY_B:
      76      for (i = 0; i < len; i++)
      77        __objc_gc_setup_array (mask, type, offset);
      78      break;
      79  
      80    case _C_STRUCT_B:
      81      for (i = 0; i < len; i++)
      82        __objc_gc_setup_struct (mask, type, offset);
      83      break;
      84  
      85    case _C_UNION_B:
      86      for (i = 0; i < len; i++)
      87        __objc_gc_setup_union (mask, type, offset);
      88      break;
      89  
      90    default:
      91      break;
      92    }
      93  }
      94  
      95  static void
      96  __objc_gc_setup_struct (GC_bitmap mask, const char *type, int offset)
      97  {
      98    struct objc_struct_layout layout;
      99    unsigned int position;
     100    const char *mtype;
     101  
     102    objc_layout_structure (type, &layout);
     103  
     104    while (objc_layout_structure_next_member (&layout))
     105      {
     106        BOOL gc_invisible = NO;
     107  
     108        objc_layout_structure_get_info (&layout, &position, NULL, &mtype);
     109  
     110        /* Skip the variable name */
     111        if (*mtype == '"')
     112  	{
     113  	  for (mtype++; *mtype++ != '"';)
     114  	    /* do nothing */;
     115  	}
     116  
     117        if (*mtype == _C_GCINVISIBLE)
     118  	{
     119  	  gc_invisible = YES;
     120  	  mtype++;
     121  	}
     122  
     123        /* Add to position the offset of this structure */
     124        position += offset;
     125  
     126        switch (*mtype) {
     127        case _C_ID:
     128        case _C_CLASS:
     129        case _C_SEL:
     130        case _C_PTR:
     131        case _C_CHARPTR:
     132        case _C_ATOM:
     133  	if (! gc_invisible)
     134  	  SET_BIT_FOR_OFFSET (mask, position);
     135  	break;
     136  
     137        case _C_ARY_B:
     138  	__objc_gc_setup_array (mask, mtype, position);
     139  	break;
     140  
     141        case _C_STRUCT_B:
     142  	__objc_gc_setup_struct (mask, mtype, position);
     143  	break;
     144  
     145        case _C_UNION_B:
     146  	__objc_gc_setup_union (mask, mtype, position);
     147  	break;
     148  
     149        default:
     150          break;
     151        }
     152      }
     153  }
     154  
     155  static void
     156  __objc_gc_setup_union (GC_bitmap mask, const char *type, int offset)
     157  {
     158    /* Sub-optimal, quick implementation: assume the union is made of
     159       pointers, set up the mask accordingly. */
     160  
     161    int i, size, align;
     162  
     163    /* Skip the variable name */
     164    if (*type == '"')
     165      {
     166        for (type++; *type++ != '"';)
     167  	/* do nothing */;
     168      }
     169  
     170    size = objc_sizeof_type (type);
     171    align = objc_alignof_type (type);
     172  
     173    offset = ROUND (offset, align);
     174    for (i = 0; i < size; i += sizeof (void *))
     175      {
     176        SET_BIT_FOR_OFFSET (mask, offset);
     177        offset += sizeof (void *);
     178      }
     179  }
     180  
     181  
     182  /* Iterates over the types in the structure that represents the class
     183     encoding and sets the bits in mask according to each ivar type.  */
     184  static void
     185  __objc_gc_type_description_from_type (GC_bitmap mask, const char *type)
     186  {
     187    struct objc_struct_layout layout;
     188    unsigned int offset, align;
     189    const char *ivar_type;
     190  
     191    objc_layout_structure (type, &layout);
     192  
     193    while (objc_layout_structure_next_member (&layout))
     194      {
     195        BOOL gc_invisible = NO;
     196  
     197        objc_layout_structure_get_info (&layout, &offset, &align, &ivar_type);
     198  
     199        /* Skip the variable name */
     200        if (*ivar_type == '"')
     201  	{
     202  	  for (ivar_type++; *ivar_type++ != '"';)
     203  	    /* do nothing */;
     204  	}
     205  
     206        if (*ivar_type == _C_GCINVISIBLE)
     207  	{
     208  	  gc_invisible = YES;
     209  	  ivar_type++;
     210  	}
     211  
     212        switch (*ivar_type) {
     213        case _C_ID:
     214        case _C_CLASS:
     215        case _C_SEL:
     216        case _C_PTR:
     217        case _C_CHARPTR:
     218          if (! gc_invisible)
     219            SET_BIT_FOR_OFFSET (mask, offset);
     220  	break;
     221  
     222        case _C_ARY_B:
     223  	__objc_gc_setup_array (mask, ivar_type, offset);
     224  	break;
     225  
     226        case _C_STRUCT_B:
     227  	__objc_gc_setup_struct (mask, ivar_type, offset);
     228  	break;
     229  
     230        case _C_UNION_B:
     231  	__objc_gc_setup_union (mask, ivar_type, offset);
     232  	break;
     233  
     234        default:
     235          break;
     236        }
     237      }
     238  }
     239  
     240  /* Computes in *type the full type encoding of this class including
     241     its super classes. '*size' gives the total number of bytes allocated
     242     into *type, '*current' the number of bytes used so far by the
     243     encoding. */
     244  static void
     245  __objc_class_structure_encoding (Class class, char **type, int *size,
     246                                   int *current)
     247  {
     248    int i, ivar_count;
     249    struct objc_ivar_list *ivars;
     250  
     251    if (! class)
     252      {
     253        strcat (*type, "{");
     254        (*current)++;
     255        return;
     256      }
     257  
     258    /* Add the type encodings of the super classes */
     259    __objc_class_structure_encoding (class->super_class, type, size, current);
     260  
     261    ivars = class->ivars;
     262    if (! ivars)
     263      return;
     264  
     265    ivar_count = ivars->ivar_count;
     266  
     267    for (i = 0; i < ivar_count; i++)
     268      {
     269        struct objc_ivar *ivar = &(ivars->ivar_list[i]);
     270        const char *ivar_type = ivar->ivar_type;
     271        int len = strlen (ivar_type);
     272  
     273        if (*current + len + 1 >= *size)
     274          {
     275            /* Increase the size of the encoding string so that it
     276               contains this ivar's type. */
     277            *size = ROUND (*current + len + 1, 10);
     278            *type = objc_realloc (*type, *size);
     279          }
     280        strcat (*type + *current, ivar_type);
     281        *current += len;
     282      }
     283  }
     284  
     285  
     286  /* Allocates the memory that will hold the type description for class
     287     and calls the __objc_class_structure_encoding that generates this
     288     value. */
     289  void
     290  __objc_generate_gc_type_description (Class class)
     291  {
     292    GC_bitmap mask;
     293    int bits_no, size;
     294    int type_size = 10, current;
     295    char *class_structure_type;
     296  
     297    if (! CLS_ISCLASS (class))
     298      return;
     299  
     300    /* We have to create a mask in which each bit counts for a pointer member.
     301       We take into consideration all the non-pointer instance variables and we
     302       round them up to the alignment. */
     303  
     304    /* The number of bits in the mask is the size of an instance in bytes divided
     305       by the size of a pointer. */
     306    bits_no = (ROUND (class_getInstanceSize (class), sizeof (void *))
     307               / sizeof (void *));
     308    size = ROUND (bits_no, BITS_PER_WORD) / BITS_PER_WORD;
     309    mask = objc_atomic_malloc (size * sizeof (int));
     310    memset (mask, 0, size * sizeof (int));
     311  
     312    class_structure_type = objc_atomic_malloc (type_size);
     313    *class_structure_type = current = 0;
     314    __objc_class_structure_encoding (class, &class_structure_type,
     315                                     &type_size, &current);
     316    if (current + 1 == type_size)
     317      class_structure_type = objc_realloc (class_structure_type, ++type_size);
     318    strcat (class_structure_type + current, "}");
     319  #ifdef DEBUG
     320    printf ("type description for '%s' is %s\n", class->name, class_structure_type);
     321  #endif
     322    
     323    __objc_gc_type_description_from_type (mask, class_structure_type);
     324    objc_free (class_structure_type);
     325  
     326  #ifdef DEBUG
     327    printf ("  mask for '%s', type '%s' (bits %d, mask size %d) is:",
     328  	  class_structure_type, class->name, bits_no, size);
     329    {
     330      int i;
     331      for (i = 0; i < size; i++)
     332        printf (" %lx", mask[i]);
     333    }
     334    puts ("");
     335  #endif
     336  
     337    class->gc_object_type = (void *) GC_make_descriptor (mask, bits_no);
     338  }
     339  
     340  
     341  /* Returns YES if type denotes a pointer type, NO otherwise */
     342  static inline BOOL
     343  __objc_ivar_pointer (const char *type)
     344  {
     345    type = objc_skip_type_qualifiers (type);
     346  
     347    return (*type == _C_ID
     348            || *type == _C_CLASS
     349            || *type == _C_SEL
     350            || *type == _C_PTR
     351            || *type == _C_CHARPTR
     352            || *type == _C_ATOM);
     353  }
     354  
     355  
     356  /* Mark the instance variable whose name is given by ivarname as a
     357     weak pointer (a pointer hidden to the garbage collector) if
     358     gc_invisible is true. If gc_invisible is false it unmarks the
     359     instance variable and makes it a normal pointer, visible to the
     360     garbage collector.
     361  
     362     This operation only makes sense on instance variables that are
     363     pointers.  */
     364  void
     365  class_ivar_set_gcinvisible (Class class, const char *ivarname,
     366                              BOOL gc_invisible)
     367  {
     368    int i, ivar_count;
     369    struct objc_ivar_list *ivars;
     370  
     371    if (! class || ! ivarname)
     372      return;
     373  
     374    ivars = class->ivars;
     375    if (! ivars)
     376      return;
     377  
     378    ivar_count = ivars->ivar_count;
     379  
     380    for (i = 0; i < ivar_count; i++)
     381      {
     382        struct objc_ivar *ivar = &(ivars->ivar_list[i]);
     383        const char *type;
     384  
     385        if (! ivar->ivar_name || strcmp (ivar->ivar_name, ivarname))
     386  	continue;
     387  
     388        assert (ivar->ivar_type);
     389        type = ivar->ivar_type;
     390  
     391        /* Skip the variable name */
     392        if (*type == '"')
     393  	{
     394  	  for (type++; *type++ != '"';)
     395  	    /* do nothing */;
     396  	}
     397  
     398        if (*type == _C_GCINVISIBLE)
     399  	{
     400  	  char *new_type;
     401  	  size_t len;
     402  
     403  	  if (gc_invisible || ! __objc_ivar_pointer (type))
     404  	    return;	/* The type of the variable already matches the
     405  			   requested gc_invisible type */
     406  
     407  	  /* The variable is gc_invisible so we make it gc visible.  */
     408  	  new_type = objc_atomic_malloc (strlen(ivar->ivar_type));
     409  	  len = (type - ivar->ivar_type);
     410  	  memcpy (new_type, ivar->ivar_type, len);
     411  	  new_type[len] = 0;
     412  	  strcat (new_type, type + 1);
     413  	  ivar->ivar_type = new_type;
     414  	}
     415        else
     416  	{
     417  	  char *new_type;
     418  	  size_t len;
     419  
     420  	  if (! gc_invisible || ! __objc_ivar_pointer (type))
     421  	    return;	/* The type of the variable already matches the
     422  			   requested gc_invisible type */
     423  
     424  	  /* The variable is gc visible so we make it gc_invisible.  */
     425  	  new_type = objc_malloc (strlen(ivar->ivar_type) + 2);
     426  
     427  	  /* Copy the variable name.  */
     428  	  len = (type - ivar->ivar_type);
     429  	  memcpy (new_type, ivar->ivar_type, len);
     430  	  /* Add '!'.  */
     431  	  new_type[len++] = _C_GCINVISIBLE;
     432  	  /* Copy the original types.  */
     433  	  strcpy (new_type + len, type);
     434  
     435  	  ivar->ivar_type = new_type;
     436  	}
     437  
     438        __objc_generate_gc_type_description (class);
     439        return;
     440      }
     441  
     442    /* Search the instance variable in the superclasses */
     443    class_ivar_set_gcinvisible (class->super_class, ivarname, gc_invisible);
     444  }
     445  
     446  #else /* !OBJC_WITH_GC */
     447  
     448  void
     449  __objc_generate_gc_type_description (Class class __attribute__ ((__unused__)))
     450  {
     451  }
     452  
     453  void class_ivar_set_gcinvisible (Class class __attribute__ ((__unused__)),
     454  				 const char *ivarname __attribute__ ((__unused__)),
     455  				 BOOL gc_invisible __attribute__ ((__unused__)))
     456  {
     457  }
     458  
     459  #endif /* OBJC_WITH_GC */